我有一个禁用调整大小功能的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;
}
答案 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;
}