Disable WPF Window Focus

You can prevent a WPF Window from activating on mouse click by adding a custom WndProc and handling WM_MOUSEACTIVATE:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);
    var source = PresentationSource.FromVisual(this) as HwndSource;
    source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == WM_MOUSEACTIVATE)
    {
        handled = true;
        return new IntPtr(MA_NOACTIVATE);
    }
    else return IntPtr.Zero;
}
private const int WM_MOUSEACTIVATE = 0x0021;
private const int MA_NOACTIVATE = 0x0003;

References:

  • MSDN WM_MOUSEACTIVATE: https://msdn.microsoft.com/en-us/library/windows/desktop/ms645612(v=vs.85).aspx
  • How to handle WndProc messages in WPF: How to handle WndProc messages in WPF?
  • Notification Window – Preventing the window from ever getting focus: Notification Window - Preventing the window from ever getting focus

Found the answer elsewhere:

protected override void OnSourceInitialized(EventArgs e)
{
    base.OnSourceInitialized(e);

    //Set the window style to noactivate.
    var helper = new WindowInteropHelper(this);
    SetWindowLong(helper.Handle, GWL_EXSTYLE,
        GetWindowLong(helper.Handle, GWL_EXSTYLE) | WS_EX_NOACTIVATE);
}   

private const int GWL_EXSTYLE = -20;
private const int WS_EX_NOACTIVATE = 0x08000000;

[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);

Prevent certain top-level windows from getting activated in WPF:

I tried the Win32 solution given here but it didn't work for me. While it does seem to prevent window "activation," the Focus is left in limbo afterwards, not restored to another eligible window in your application. Instead, the following worked for me:

First, make sure that all the non-primary windows have their Owner property set to the main Window. I do this in the constructor of the sub-window, in which case one must take some steps (not discussed here) to make sure that the main Window is loaded first.

public MySubWindow()
{
    if ((base.Owner = Application.Current.MainWindow) == null)
        throw new Exception();

    InitializeComponent();
}

Setting the Owner property should also ensure that the sub windows stay on top of the main window. For the sub window(s), set the following properties as indicated (XAML or code):

ShowActivated="False"
Focusable="False"
ShowInTaskbar="False"
IsEnabled="False"
FocusManager.IsFocusScope="False"

Finally, add a handler for OnActivated to the blocked windows. I don't call the base method since it fires the Activated event. (Note that you should not switch the activation away from the Visual Studio designer since it makes the window invisible).

protected override void OnActivated(EventArgs e)
{
    if (DesignerProperties.GetIsInDesignMode(this))
        return;

    base.Owner.Activate();
}

Since .NET 3.5 SP1 WPF forms have a ShowActivated property. Set this to false and the form thus marked won't steal no focus no more.

Tags:

C#

Wpf

Focus