6

I am trying to keep one particular WPF window in focus, meaning that it should not change the window style when losing focus (e.g. like the standard Windows Taskbar). To achieve this, I hook into the WndProc to check whether the WM_NCACTIVATE or WM_ACTIVATE is set on false ( wParam == 0 ) and then mark the message as handled = true; to block the Window from being inactive. Here is some example code:

void Window_Loaded(object sender, RoutedEventArgs e)
{
    var source = HwndSource.FromHwnd(new WindowInteropHelper(this).Handle);
    if (source != null) source.AddHook(WndProc);
}

private const uint WM_NCACTIVATE = 0x0086;
private const int WM_ACTIVATE = 0x0006;
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
    if (msg == WM_NCACTIVATE)
    {
        if (wParam == new IntPtr(0))
            handled = true;
    }
    if (msg == WM_ACTIVATE)
    {

        if (wParam == new IntPtr(0))
            handled = true;
    }
    return IntPtr.Zero;
}

However, by doing this, all other WPF windows that are created from within this main window

var f = new Window();
f.ShowDialog();

never receive focus and although they are visible, the window does not react to user input both in the client area but also for the Windows minimize, maximize and close button. I am obviously doing something wrong, so any advice or pointers on how to do this the right way?

dsfgsho
  • 2,731
  • 2
  • 22
  • 39
  • The code just doesn't do what you hope it does. It merely prevents WPF from seeing the message. The window is still activated but WPF doesn't know it. So gets hopelessly confused. Preventing window de-activation requires a much bigger weapon, one that WPF doesn't have. – Hans Passant Jun 26 '13 at 12:32
  • Yes, that was what I expected. So what would be a better way to approach this? – dsfgsho Jun 26 '13 at 14:32
  • Approach *what*? A taskbar doesn't have a "style" so it is entirely unclear what problem you are trying to solve. WPF doesn't directly support creating taskbars, you create one by pinvoking SHAppBarMessage(). That googles well. – Hans Passant Jun 26 '13 at 14:49
  • I am indeed using SHAppBarMessage to register a new appbar. What i am trying to do is disable the activation/deactivation behavior of the Window that is registered as an appbar (in my case a WPF window). I have been looking at setting `ABM_ACTIVATE` or `ABM_SETSTATE` but these do not change the visual appearance of the registered taskbar. – dsfgsho Jun 26 '13 at 15:16

1 Answers1

4

The solution to keeping the visual style of a WPF window to active even if the window loses focus is to handle the WM_NCACTIVATE like this:

private const uint WM_NCACTIVATE = 0x0086;

private IntPtr WndProc(IntPtr hwnd, int msg, 
         IntPtr wParam, IntPtr lParam, ref bool handled)
{
    var returnvalue = IntPtr.Zero;
    if (msg == WM_NCACTIVATE)
    {
        //replace the wParam (true/false) which indicates 
            //active/inactive with always true
        returnvalue = DefWindowProc(hwnd, WM_NCACTIVATE, 
                     new IntPtr(1), new IntPtr(-1));
        handled = true;
    }
}


[DllImport("user32.dll")]
static extern IntPtr DefWindowProc(IntPtr hWnd, WindowsMessages uMsg, IntPtr wParam, IntPtr lParam);
dsfgsho
  • 2,731
  • 2
  • 22
  • 39