views:

91

answers:

1

I have a custom windows implementation in a WPF app that hooks WM_GETMINMAXINFO as follows:

    private void MaximiseWithTaskbar(System.IntPtr hwnd, System.IntPtr lParam)
    {
        MINMAXINFO mmi = (MINMAXINFO)Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));

        System.IntPtr monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);

        if (monitor != System.IntPtr.Zero)
        {
            MONITORINFO monitorInfo = new MONITORINFO();
            GetMonitorInfo(monitor, monitorInfo);
            RECT rcWorkArea = monitorInfo.rcWork;
            RECT rcMonitorArea = monitorInfo.rcMonitor;
            mmi.ptMaxPosition.x = Math.Abs(rcWorkArea.left - rcMonitorArea.left);
            mmi.ptMaxPosition.y = Math.Abs(rcWorkArea.top - rcMonitorArea.top);
            mmi.ptMaxSize.x = Math.Abs(rcWorkArea.right - rcWorkArea.left);
            mmi.ptMaxSize.y = Math.Abs(rcWorkArea.bottom - rcWorkArea.top);
            mmi.ptMinTrackSize.x = Convert.ToInt16(this.MinWidth * (desktopDpiX / 96));
            mmi.ptMinTrackSize.y = Convert.ToInt16(this.MinHeight * (desktopDpiY / 96));
        }

        Marshal.StructureToPtr(mmi, lParam, true);
    }

It all works a treat and it allows me to have a borderless window maximized without having it sit on to of the task bar, which is great, but it really doesn't like being moved between monitors with the new Win7 keyboard shortcuts.

Whenever the app is moved with Win+Shift+Left/Right the WM_GETMINMAXINFO message is received, as I'd expect, but MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST) returns the monitor the application has just been moved FROM, rather than the monitor it is moving TO, so if the monitors are of differing resolutions the window end up the wrong size.

I'm not sure if there's something else I can call, other then MonitorFromWindow, or whether there's a "moving monitors" message I can hook prior to WM_GETMINMAXINFO. I'm assuming there is a way to do it because "normal" windows work just fine.

+1  A: 

According to the MSDN page the WM_GETMINMAXINFO is sent:

"when the size or position of the window is about to change"

which explains why your call to MonitorFromWindow returns the previous monitor.

How about using the WM_WINDOWPOSCHANGED message? It's sent after every time the window is moved. You can get the HWND from the WINDOWPOS structure and use that in a MonitorFromWindow call to get the monitor. When a subsequent WM_GETMINMAXINFO is sent you can use that as you do now.

voyce
Thanks. I'll hook it and see - I'm guessing I just manually resize the window myself? Hopefully that will work even though it's maximised at the time.
Steven Robbins
I tried this and it didn't seem to work, although it's nigh on impossible to debug because switching back and forth to the debugger fires the event again. I will accept it anyway, because it should work, and I'll try and spend more time on it later. Thanks.
Steven Robbins