Window does not resize properly when moved to larger display

前端 未结 2 2050
抹茶落季
抹茶落季 2021-02-05 14:23

My WPF application is exhibiting strange behavior on my two monitor laptop development system. The second monitor has a resolution of 1920 x 1080; the laptop\'s resolution is 1

相关标签:
2条回答
  • 2021-02-05 15:05

    I've finally resolved this problem. It turns out that what I needed to do is change one line in the switch statement in the WindowProcedureHook method:

            case WinMessages.WM_GETMINMAXINFO:
                // lParam has a pointer to the MINMAXINFO structure.  Marshal it into managed memory.
                MINMAXINFO mmi = (MINMAXINFO) Marshal.PtrToStructure( lParam, typeof( MINMAXINFO ) );
                if ( monitor != IntPtr.Zero ) {
                    MONITORINFO monitorInfo = new MONITORINFO();
                    GetMonitorInfo( monitor, monitorInfo );
    
                    // Get the Monitor's working area
                    RECT rcWorkArea    = monitorInfo.rcWork;
                    RECT rcMonitorArea = monitorInfo.rcMonitor;
    
                    // Adjust the maximized size and position to fit the work area of the current monitor
                    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 );
                }
    
                // Copy our changes to the mmi object back to the original
                Marshal.StructureToPtr( mmi, lParam, true );
                handled = false; // This line used to set handled to true
                return IntPtr.Zero;
    

    With this change, the code that's normally executed in WPF when the WM_GETMINMAXINFO message is received still runs, but it uses the change to the MINMAXINFO object made by the code in order to do its work. With this change, the WPF window handles the resolution changes properly.

    EDIT

    And it turns out that the code no longer needs to look specifically for a screen resolution or installed monitor change. That is, the SystemEvent.DisplaySettingsChanged event handler is no longer needed.

    0 讨论(0)
  • 2021-02-05 15:07

    Turns out its not a complicated fix. The MinTrackSize point (bounds) needs to be set to the working area dimensions of the secondary monitor.

    private static void WmGetMinMaxInfo(System.IntPtr hwnd, System.IntPtr lParam)
    {
        MINMAXINFO mmi = (MINMAXINFO)System.Runtime.InteropServices.Marshal.PtrToStructure(lParam, typeof(MINMAXINFO));
    
        /*  0x0001        // center rect to monitor 
            0x0000        // clip rect to monitor 
            0x0002        // use monitor work area 
            0x0000        // use monitor entire area */
    
        int MONITOR_DEFAULTTONEAREST = 0x00000002;
        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;
    
            // set the maximize size of the application
            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);
    
            // reset the bounds of the application to the monitor working dimensions
            mmi.ptMaxTrackSize.x = mmi.ptMaxSize.x;
            mmi.ptMaxTrackSize.y = mmi.ptMaxSize.y;
        }
    
        System.Runtime.InteropServices.Marshal.StructureToPtr(mmi, lParam, true);
    }
    
    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct MINMAXINFO
    {
        public POINT ptReserved;
        public POINT ptMaxSize;
        public POINT ptMaxPosition;
        public POINT ptMinTrackSize;
        public POINT ptMaxTrackSize;
    };
    
    0 讨论(0)
提交回复
热议问题