禁用对ShowWindow函数调用的窗口反应

时间:2017-02-16 13:58:04

标签: c# wpf winapi

我有一个禁用调整大小功能的WPF窗口(WindowStyle = None,ResizeMode = CanMinimize)。

除了一种情况外,它工作正常。如果某个应用程序(即AutoHotKey)在我的窗口上使用SW_MAXIMIZE选项调用WIN API函数ShowWindow,那么我的窗口将重新定位到桌面上的(0,0)坐标,而不会更改尺寸,并且用户无法进一步在屏幕上移动它。

如何禁用此行为?我希望窗口忽略我窗口上的这个调用。

我已经尝试过对WM_WINDOWPOSCHANGING事件做出反应,但这只适用于用户最小化窗口。在最小化并恢复后,它将再次重新定位到(0,0)坐标。

private IntPtr ProcessMessage(IntPtr windowHandle, int msg, IntPtr wideParam, IntPtr leftParam, ref bool handled)
{
    Msg windowsMessage = (Msg)msg;
    switch (windowsMessage)
    {
        case Msg.WM_WINDOWPOSCHANGING:
            {
                WindowPos windowPos = (WindowPos)Marshal.PtrToStructure(leftParam, typeof(WindowPos));

                if (IsNoClientAction(windowPos) && !IsMinimizing(windowPos) && window.WindowState == WindowState.Normal)
                {
                    windowPos.Flags = SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOMOVE;
                    handled = true;
                    Marshal.StructureToPtr(windowPos, leftParam, true);
                }

                break;
            }
    }

    return IntPtr.Zero;
}

private static bool IsNoClientAction(WindowPos windowPos)
{
    return (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTSIZE) != 0 || (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTMOVE) != 0;
}

private static bool IsMinimizing(WindowPos windowPos)
{
    return windowPos.Left == -32000 && windowPos.Top == -32000;
}

1 个答案:

答案 0 :(得分:0)

我已经分析了user32.dll对窗口做了什么,并根据它找出了解决方案。在向Wndproc发送任何消息之前,它会更新GWL_STYLE窗口标志,为其启用WS_MAXIMIZE。因此,窗口状态变得破坏,并且仅通过处理窗口消息几乎不能处理进一步的行为。

要使用ShowWindow选项禁用SW_MAXIMIZE上的窗口反应,我会在处理WM_WINDOWPOSCHANGING时设置此标记:

private IntPtr ProcessMessage(IntPtr windowHandle, int msg, IntPtr wideParam, IntPtr leftParam, ref bool handled)
{
    Msg windowsMessage = (Msg)msg;
    switch (windowsMessage)
    {
        case Msg.WM_WINDOWPOSCHANGING:
            {
                WindowPos windowPos = (WindowPos)Marshal.PtrToStructure(leftParam, typeof(WindowPos));

                if (IsNoClientAction(windowPos))
                {
                    WindowStyles styles = (WindowStyles)WindowsAPI.GetWindowLongPtr(windowHandle, GWL.GWL_STYLE);
                    if ((styles & WindowStyles.WS_MAXIMIZE) != 0)
                    {
                        windowPos.Flags |= SetWindowPosFlags.SWP_NOSIZE | SetWindowPosFlags.SWP_NOMOVE;
                        WindowsAPI.SetWindowLongPtr(new HandleRef(this, windowHandle), GWL.GWL_STYLE, (IntPtr)(long)(styles ^ WindowStyles.WS_MAXIMIZE));
                        handled = true;
                        Marshal.StructureToPtr(windowPos, leftParam, true);
                    }
                }

                break;
            }
    }

    return IntPtr.Zero;
}

private static bool IsNoClientAction(WindowPos windowPos)
{
    return (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTSIZE) != 0 || (windowPos.Flags & SetWindowPosFlags.SWP_NOCLIENTMOVE) != 0;
}