Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Handling WM_NCACTIVATE in startup window blocks all other windows

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?

like image 891
dsfgsho Avatar asked Oct 04 '22 17:10

dsfgsho


1 Answers

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);
like image 51
dsfgsho Avatar answered Oct 12 '22 12:10

dsfgsho