Cody
Cody

Reputation: 3764

Determining if a form is completely off screen

I am developing an application that remembers the user's preferences as to where the form was last located on the screen. In some instances the user will have it on a secondary screen, and then fire the app up later without the second screen (sometimes having the form appear off screen). Other times the user will change their resolution resulting in a similar effect.

I was hoping to do this checking in the Form_Shown event handler. Basically I want to determine whether the form is completely off screen so I can re-position it.

Any advice?

Upvotes: 53

Views: 20579

Answers (8)

glopes
glopes

Reputation: 4390

A one-liner solution using DesktopBounds:

Array.Exists(Screen.AllScreens, screen => screen.WorkingArea.Contains(DesktopBounds))

Upvotes: 0

Tom
Tom

Reputation: 577

None of these work if a monitor happens to be off. The Screen.AllScreens function will always return the number of screens even if one is off.

Upvotes: 1

CrazyTim
CrazyTim

Reputation: 7334

Complete solution here (based on all answers). I have added a parameter MinPercentOnScreen where at least this % of pixels must be visible across all screens/displays. So if this returns false you will need to move the window's position back to default.

// Return True if a certain percent of a rectangle is shown across the total screen area of all monitors, otherwise return False.
public bool IsOnScreen(System.Drawing.Point RecLocation, System.Drawing.Size RecSize, double MinPercentOnScreen = 0.2)
{
    double PixelsVisible = 0;
    System.Drawing.Rectangle Rec = new System.Drawing.Rectangle(RecLocation, RecSize);

    foreach (Screen Scrn in Screen.AllScreens)
    {
        System.Drawing.Rectangle r = System.Drawing.Rectangle.Intersect(Rec, Scrn.WorkingArea);
        // intersect rectangle with screen
        if (r.Width != 0 & r.Height != 0)
        {
            PixelsVisible += (r.Width * r.Height);
            // tally visible pixels
        }
    }
    return PixelsVisible >= (Rec.Width * Rec.Height) * MinPercentOnScreen;
}

Implementation:

return IsOnScreen(this.Location, this.Size);

Upvotes: 12

Andrija
Andrija

Reputation: 14493

Check with this function if Form is fully on screen:

public bool IsOnScreen( Form form )
{
   Screen[] screens = Screen.AllScreens;
   foreach( Screen screen in screens )
   {
      Rectangle formRectangle = new Rectangle( form.Left, form.Top, 
                                               form.Width, form.Height );

      if( screen.WorkingArea.Contains( formRectangle ) )
      {
         return true;
      }
   }

   return false;
}

Checking only top left point if it's on screen:

public bool IsOnScreen( Form form )
{
   Screen[] screens = Screen.AllScreens;
   foreach( Screen screen in screens )
   {
      Point formTopLeft = new Point( form.Left, form.Top );

      if( screen.WorkingArea.Contains( formTopLeft ) )
      {
         return true;
      }
   }

   return false;
}

Upvotes: 71

salle55
salle55

Reputation: 2181

For WPF (based on Matthias Loerkes answer)

Add a reference to System.Windows.Forms and System.Drawing.

//using System.Windows.Forms;

public bool IsOnScreen(Window window)
{
   var windowRect = new System.Drawing.Rectangle((int)window.Left, (int)window.Top, (int)window.Width, (int)window.Height);
   return Screen.AllScreens.Any(s => s.WorkingArea.IntersectsWith(windowRect));
}

Upvotes: 1

Matthias Loerke
Matthias Loerke

Reputation: 2187

Combining all the solutions above with the "IntersectsWith"-method and LINQ-extensions give us in short:

public bool IsOnScreen(Form form) 
{
   // Create rectangle
   Rectangle formRectangle = new Rectangle(form.Left, form.Top, form.Width, form.Height); 

   // Test
   return Screen.AllScreens.Any(s => s.WorkingArea.IntersectsWith(formRectangle));
}

Upvotes: 22

Sean
Sean

Reputation: 41

Old thread, but still helpful! Cody and Andrija- thanks for the code. I had to make a couple of minor adjustments: Instead of screen.WorkingArea.Intersect(formRectangle); I used formRectangle.Intersect(screen.WorkingArea); since Intersect() replaces its object with the intersection. If the form is completely off the screen, formRectangle after the intersection is (0,0,0,0), and Contains() returns true. So I also check to see if formRectangle Top, Left, Width and Height are not all 0 before returning true. Now the code returns true if any part of the form is on screen, and false if no part is on screen.

Upvotes: 4

Allen Rice
Allen Rice

Reputation: 19446

Check the screens resolution before you position the window. That will allow you to figure out if you where going to place it outside the bounds of the resolution, before you actually do it.

Upvotes: 0

Related Questions