在启动窗口中处理WM_NCACTIVATE会阻止所有其他窗口

时间:2013-06-25 13:05:39

标签: c# wpf winapi wndproc

我试图让一个特定的WPF窗口保持焦点,这意味着它在失去焦点时不应该改变窗口样式(例如像标准的Windows任务栏)。为实现此目的,我勾选WndProc以检查WM_NCACTIVATEWM_ACTIVATE是否设置为false(wParam == 0),然后将邮件标记为handled = true;阻止Window处于非活动状态。以下是一些示例代码:

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;
}

但是,通过执行此操作,从此主窗口中创建的所有其他WPF窗口

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

永远不会获得焦点,虽然它们是可见的,但窗口不会对客户区域中的用户输入做出反应,也会对Windows最小化,最大化和关闭按钮做出反应。我显然做错了什么,所以有任何建议或指示如何以正确的方式做到这一点?

1 个答案:

答案 0 :(得分:4)

即使窗口失去焦点,保持WPF窗口的视觉样式处于活动状态的解决方案是像这样处理WM_NCACTIVATE

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