在WndProc中处理AeroSnap消息

在我的C#.NET 4应用程序中,我使用WndProc处理一些消息,主要是处理从全屏调整应用程序的大小。

现在我只是处理SC_MAXIMIZEWM_NCLBUTTONDBLCLK以确定窗口是否正在resize或从最大化状态resize(我知道我不需要WndProc来处理SC_MAXIMIZE ,但是当我使用时, Form_Resize似乎没有触发WM_NCLBUTTONDBLCLK消息双击应用程序的标题栏。

现在我注意到,如果我将Aero Snap窗口移到屏幕顶部以使其最大化,则上述消息都不会发布,因此当通过Aero Snap最大化窗口时,不会应用某些逻辑。 我只想处理消息,如果窗口被捕捉到屏幕的顶部而不是右边或左边,或者窗口是从最大化位置取消的。

我找不到任何与Aero Snap相关的窗口消息。 有谁知道这些消息的任何参考?

我猜这里没有任何特别的消息; Aero可能只是使用普通的Win32 API – ShowWindow(SW_MAXIMIZE)等。

理解SC_消息的原因是那些是来自菜单的请求,要求窗口resize/恢复/ etc本身,但这不是改变窗口大小的唯一机制。 可能发生的是当窗口获得SC_MAXIMIZE时,DefWndProc通过调用ShowWindow(SW_MAXIMIZE)来实现。

最好的方法是收听窗口收到的WM_SIZE消息,无论触发大小更改的是什么:系统菜单,API或其他方法。 特别是,lParam会告诉您窗口是否已最大化(SIZE_MAXIMIZED)或已恢复(SIZE_RESTORED)。

以下是处理Maximize而不是WM_SIZE消息的WM_WINDOWPOSCHANGING消息的代码。 感谢关于SO的20个或更多问题,我必须阅读以找到将它们放在一起并使其工作的所有位。 这解决了我使用不同分辨率的多台显示器遇到的问题。

 //register the hook public static void WindowInitialized(Window window) { IntPtr handle = (new WindowInteropHelper(window)).Handle; var hwndSource = HwndSource.FromHwnd(handle); if (hwndSource != null) { hwndSource.AddHook(WindowProc); } } //the important bit private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled) { switch (msg) { case 0x0046: //WINDOWPOSCHANGING var winPos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS)); var monitorInfo = new MONITORINFO(); IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MonitorDefaultToNearest); GetMonitorInfo(monitorContainingApplication, monitorInfo); RECT rcWorkArea = monitorInfo.rcWork; //check for a framechange - but ignore initial draw. x,y is top left of current monitor so must be a maximise if (((winPos.flags & SWP_FRAMECHANGED) == SWP_FRAMECHANGED) && (winPos.flags & SWP_NOSIZE) != SWP_NOSIZE && winPos.x == rcWorkArea.left && winPos.y == rcWorkArea.top) { //set max size to the size of the *current* monitor var width = Math.Abs(rcWorkArea.right - rcWorkArea.left); var height = Math.Abs(rcWorkArea.bottom - rcWorkArea.top); winPos.cx = width; winPos.cy = height; Marshal.StructureToPtr(winPos, lParam, true); handled = true; } break; } return (IntPtr)0; } //all the helpers for dealing with this COM crap [DllImport("user32")] internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi); [DllImport("user32")] internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags); private const int MonitorDefaultToNearest = 0x00000002; [StructLayout(LayoutKind.Sequential)] public struct WINDOWPOS { public IntPtr hwnd; public IntPtr hwndInsertAfter; public int x; public int y; public int cx; public int cy; public int flags; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)] public class MONITORINFO { public int cbSize = Marshal.SizeOf(typeof(MONITORINFO)); public RECT rcMonitor; public RECT rcWork; public int dwFlags; } [StructLayout(LayoutKind.Sequential, Pack = 0)] public struct RECT { public int left; public int top; public int right; public int bottom; }