Using SetWindowLong()
and WS_EX_NOACTIVATE
I've made a window non-activatable.
I made a mini project to reproduce the issue: http://s000.tinyupload.com/index.php?file_id=78888532457762447347
Basically a WPF application with two windows:
MainWindow
// XAML code
<Window x:Class="CS_test.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Background="LightGray" Height="300" Width="400">
<Grid>
<TextBox Width="300" Height="200"></TextBox>
</Grid>
</Window>
// C# code
namespace CS_test
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
new NonActiveWindow().Show();
}
}
}
NonActiveWindow
// XAML code
<Window x:Class="CS_test.NonActiveWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="NonActiveWindow" Height="300" Width="300"
Loaded="Window_Loaded">
<Grid>
</Grid>
</Window>
// C# code
namespace CS_test
{
public partial class NonActiveWindow : Window
{
[DllImport("user32.dll")]
public static extern IntPtr SetWindowLong(IntPtr hWnd, int nIndex, int dwNewLong);
[DllImport("user32.dll")]
public static extern int GetWindowLong(IntPtr hWnd, int nIndex);
private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 0x08000000;
public NonActiveWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
WindowInteropHelper windowHelper = new WindowInteropHelper(this);
SetWindowLong(windowHelper.Handle, GWL_EXSTYLE, GetWindowLong(windowHelper.Handle, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
}
}
}
I know it is possible to fix the issue by instantiating NonActiveWindow
in a separate thread (with a separate Dispatcher), but I can't use this approach due to threading issues.
Is there a way to prevent the focus loss without creating the non-activatable window in a separate thread?
Edit:
Video to show the issue (in response to Justins answer):
https://www.youtube.com/watch?v=6RNmJc7ya48
And just in case anyone wonders why the window isn't updated while dragging: Create a window using the WS_EX_NOACTIVATE flag ,but it can't be dragged until I release the mouse.
The ShowActivated
property is working fine for me:
public MainWindow()
{
InitializeComponent();
var otherWindow = new NonActiveWindow()
{
ShowActivated = false
};
otherWindow.Show();
}
My OtherWindow
is just an empty WPF window and doesn't have any of the P/Invoke calls that your example has.
Note that MainWindow
is shown very slightly after OtherWindow
is shown because this call is in the constructor. If you want to fix this then you should call Show
outside of the constructor, for example in the Loaded
event.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With