Here is the code for handling WM_WINDOWPOSCHANGING message for Maximise instead of WM_SIZE message. Thanks to the 20 or more questions on SO that I had to read to find all the bits to put it together and get it working. This addresses the problems that I was having with multiple monitors using different resolutions.
public static void WindowInitialized(Window window)
{
IntPtr handle = (new WindowInteropHelper(window)).Handle;
var hwndSource = HwndSource.FromHwnd(handle);
if (hwndSource != null)
{
hwndSource.AddHook(WindowProc);
}
}
private static IntPtr WindowProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
switch (msg)
{
case 0x0046:
var winPos = (WINDOWPOS)Marshal.PtrToStructure(lParam, typeof(WINDOWPOS));
var monitorInfo = new MONITORINFO();
IntPtr monitorContainingApplication = MonitorFromWindow(hwnd, MonitorDefaultToNearest);
GetMonitorInfo(monitorContainingApplication, monitorInfo);
RECT rcWorkArea = monitorInfo.rcWork;
if (((winPos.flags & SWP_FRAMECHANGED) == SWP_FRAMECHANGED) && (winPos.flags & SWP_NOSIZE) != SWP_NOSIZE && winPos.x == rcWorkArea.left && winPos.y == rcWorkArea.top)
{
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;
}
[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;
}