Wednesday, April 10, 2013

Detect WPF Window out of bound for multiple monitor

            Point p =new Point(left, top);
            bool outOfBoundHorizontal = p.X < SystemParameters.VirtualScreenLeft || p.X > SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth;
            bool outOfBoundVertical = p.Y < SystemParameters.VirtualScreenTop || p.Y > SystemParameters.VirtualScreenTop + SystemParameters.VirtualScreenHeight;

Note that VirtualScreenHeight/Width considered Multiple Monitor with various Display Positioning, It can start at negative  and to position 1/3, use 1/0/3.0*(SystemParameters.VirtualScreenLeft + SystemParameters.VirtualScreenWidth), not just width.

TO reposition find Primary Monitor
           if (outOfBoundHorizontal || outOfBoundVertical)
            {
                var primaryMonitor = Screen.AllScreens.FirstOrDefault(s => s.Primary);
                if (primaryMonitor == null)
                {
                  wnd.Left = 0;
                  wnd.Top = 0; 
                }
                else
                {
                    // Fit into Primary Monitor if possible. Note Primary Monitor start @ (0,0)
                    wnd.Left = primaryMonitor.Bounds.Left + Math.Max(primaryMonitor.Bounds.Width- wnd.Width, 0);
                    wnd.Top = primaryMonitor.Bounds.Height + Math.Max(primaryMonitor.Bounds.Height - wnd.Height, 0);                   
                }
            }

Update--- the above code does not work property due to measurement issues , flip monitor, Landscape/Portrait, L shapes.
1 point = 1/72 inch, 1 px = 1/96 inch. The size could use either px or point per Graphics.PageUnit

Rectangle hitTestRec= new System.Drawing.Rectange(left,top, new size(2,2))

var hitTestMonitor= System.Windows.Form.Screen.AllScreens.FirstOrDefault(s => s.Bounds.Contains(hitTestRect));
bool outOfBound = hitTestMonitor ==null;