Maximize WPF window on 2 monitor

南楼画角 提交于 2019-12-08 02:41:25

问题


Like title I want my WPF to maximize on 2 monitors (now my pc have 2 monitors). I set

this.Width = System.Windows.Forms.Screen.AllScreens[0].Bounds.Width + System.Windows.Forms.Screen.AllScreens[1].Bounds.Width 

but it not full, have spaced like the image. I want user click maximize button then window maximize 2 monitor. Does anyone know? Thank you all!

p/s: sorry for my bad English.


回答1:


You need to find point Left, Top, Height, Width and directly set to the window which you want to maximize

MonitorFromPoint
MonitorFromRect
MonitorFromWindow

For completeness, I present first the naive approach how the window can be maximized on the specified monitor.

void Maximize(HWND hWnd, HMONITOR hMonitor)
{
    // access monitor info
    MONITORINFO monitorInfo = { sizeof(MONITORINFO) };
    GetMonitorInfo(hMonitor, &monitorInfo);

    // restore window to normal size if it is not yet
    ShowWindow(hWnd, SW_RESTORE);

    // move window to the monitor
    SetWindowPos(hWnd, nullptr, monitorInfo.rcMonitor.left, 
    monitorInfo.rcMonitor.top, 0, 0, SWP_NOZORDER | SWP_NOSIZE);

    // maximize window
    ShowWindow(hWnd, SW_MAXIMIZE);    
}

Flickering is more obvious if function is called several times with the same input window and same target monitor. Of course, someone can argue that it is possible to obtain the current state of the window and avoid calling the function (or making some early return in the function if the state is detected to be already correct). However such handling will just add more complexity to the function. I was thinking whether it is not possible to just hide the window and perform restoration of the state just somehow in the background and only at the end show the window. But trying to inject some SetRender(hWnd, FALSE) or ShowWindow(SW_HIDE) calls just made the output even worse. After some tests, I found that changing maximize/normal window changes just one bit (WS_MAXIMIZE) in window's styles and finally with this information I get the final good solution:

void Maximize(HWND hWnd, HMONITOR hMonitor)
{
    // access monitor info
    MONITORINFO monitorInfo = { sizeof(MONITORINFO) };
    GetMonitorInfo(hMonitor, &monitorInfo);

    const LONG currStyles = GetWindowLong(hWnd, GWL_STYLE);
    SetWindowLong(hWnd, GWL_STYLE, currStyles | WS_MAXIMIZE);
    const auto rc = monitorInfo.rcMonitor;
    SetWindowPos(&CWnd::wndTop, rc.left, rc.top, rc.Width(), rc.Height(), 0);
}

And that's it. The function works as expected and if it is even called several times, there is no flickering. The function can be easily changed to also restore window to normal size by removing WS_MAXIMIZE from the window styles and calling SetWindowPos with correct rectangle information.

        [DllImport("User32.dll")]
        private static extern IntPtr MonitorFromPoint([In]System.Drawing.Point pt, [In]uint dwFlags);

        //https://msdn.microsoft.com/en-us/library/windows/desktop/dn280510(v=vs.85).aspx
        [DllImport("Shcore.dll")]
        private static extern IntPtr GetDpiForMonitor([In]IntPtr hmonitor, [In]DpiType dpiType, [Out]out uint dpiX, [Out]out uint dpiY);

        public enum DpiType
        {
            Effective = 0,
            Angular = 1,
            Raw = 2,
        }

        /// <summary>
        /// POINT aka POINTAPI
        /// </summary>
        [StructLayout(LayoutKind.Sequential)]
        public struct POINT
        {
            /// <summary>
            /// x coordinate of point.
            /// </summary>
            public int x;
            /// <summary>
            /// y coordinate of point.
            /// </summary>
            public int y;

            /// <summary>
            /// Construct a point of coordinates (x,y).
            /// </summary>
            public POINT(int x, int y)
            {
                this.x = x;
                this.y = y;
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct MINMAXINFO
        {
            public POINT ptReserved;
            public POINT ptMaxSize;
            public POINT ptMaxPosition;
            public POINT ptMinTrackSize;
            public POINT ptMaxTrackSize;
        };

        /// <summary>
        /// </summary>
        [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Auto)]
        public class MONITORINFO
        {
            /// <summary>
            /// </summary>            
            public int cbSize = Marshal.SizeOf(typeof(MONITORINFO));

            /// <summary>
            /// </summary>            
            public RECT rcMonitor = new RECT();

            /// <summary>
            /// </summary>            
            public RECT rcWork = new RECT();

            /// <summary>
            /// </summary>            
            public int dwFlags = 0;
        }


        /// <summary> Win32 </summary>
        [StructLayout(LayoutKind.Sequential, Pack = 0)]
        public struct RECT
        {
            /// <summary> Win32 </summary>
            public int left;
            /// <summary> Win32 </summary>
            public int top;
            /// <summary> Win32 </summary>
            public int right;
            /// <summary> Win32 </summary>
            public int bottom;

            /// <summary> Win32 </summary>
            public static readonly RECT Empty = new RECT();

            /// <summary> Win32 </summary>
            public int Width
            {
                get { return Math.Abs(right - left); }  // Abs needed for BIDI OS
            }
            /// <summary> Win32 </summary>
            public int Height
            {
                get { return bottom - top; }
            }

            /// <summary> Win32 </summary>
            public RECT(int left, int top, int right, int bottom)
            {
                this.left = left;
                this.top = top;
                this.right = right;
                this.bottom = bottom;
            }


            /// <summary> Win32 </summary>
            public RECT(RECT rcSrc)
            {
                this.left = rcSrc.left;
                this.top = rcSrc.top;
                this.right = rcSrc.right;
                this.bottom = rcSrc.bottom;
            }

            /// <summary> Win32 </summary>
            public bool IsEmpty
            {
                get
                {
                    // BUGBUG : On Bidi OS (hebrew arabic) left > right
                    return left >= right || top >= bottom;
                }
            }
            /// <summary> Return a user friendly representation of this struct </summary>
            public override string ToString()
            {
                if (this == RECT.Empty) { return "RECT {Empty}"; }
                return "RECT { left : " + left + " / top : " + top + " / right : " + right + " / bottom : " + bottom + " }";
            }

            /// <summary> Determine if 2 RECT are equal (deep compare) </summary>
            public override bool Equals(object obj)
            {
                if (!(obj is Rect)) { return false; }
                return (this == (RECT)obj);
            }

            /// <summary>Return the HashCode for this struct (not garanteed to be unique)</summary>
            public override int GetHashCode()
            {
                return left.GetHashCode() + top.GetHashCode() + right.GetHashCode() + bottom.GetHashCode();
            }


            /// <summary> Determine if 2 RECT are equal (deep compare)</summary>
            public static bool operator ==(RECT rect1, RECT rect2)
            {
                return (rect1.left == rect2.left && rect1.top == rect2.top && rect1.right == rect2.right && rect1.bottom == rect2.bottom);
            }

            /// <summary> Determine if 2 RECT are different(deep compare)</summary>
            public static bool operator !=(RECT rect1, RECT rect2)
            {
                return !(rect1 == rect2);
            }


        }

        [DllImport("user32")]
        internal static extern bool GetMonitorInfo(IntPtr hMonitor, MONITORINFO lpmi);

         [DllImport("User32")]
    internal static extern IntPtr MonitorFromWindow(IntPtr handle, int flags);

Links:- http://msdn.microsoft.com/en-us/library/windows/desktop/dd145071%28v=vs.85%29.aspx http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx




回答2:


I want user click maximize button then window maximize 2 monitor.

When user clicks maximize button, put this.

if (System.Windows.Forms.Screen.AllScreens.Length > 1)
{
    System.Drawing.Rectangle entireSize = System.Drawing.Rectangle.Empty;

    foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens)
        entireSize = System.Drawing.Rectangle.Union(entireSize, s.Bounds);

    //this.WindowState = NORMAL // SET Window State to Normal.


    this.Width = entireSize.Width;
    this.Height = entireSize.Height;

    this.Left = entireSize.Left;
    this.Top = entireSize.Top;

}


来源:https://stackoverflow.com/questions/52035484/maximize-wpf-window-on-2-monitor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!