禁用对ShowWindow函数调用的窗口反应
问题描述:
我有一个具有禁用调整大小功能(WindowStyle = None,ResizeMode = CanMinimize)的WPF窗口。禁用对ShowWindow函数调用的窗口反应
它工作正常,除了一种情况。如果某个应用程序(即AutoHotKey)使用SW_MAXIMIZE选项在我的窗口上调用了WIN API 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;
}
答
我已经分析了什么user32.dll
对窗口做了什么,并找出了基于此的解决方案。在发送任何消息到Wndproc
之前,它会更新GWL_STYLE
窗口的标志,使其能够使用WS_MAXIMIZE
。由于这个原因,窗口状态变得破坏,进一步的行为几乎不能通过处理窗口消息来处理。
要与SW_MAXIMIZE
选项我设置该标志回ShowWindow
禁用窗口的反应,当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;
}