How can I show a form on a second screen? - c#

I am creating a C# form application. I wanted to show the initial form on a second screen. I want to open the other form pages on the first screen. There is a resolution difference between two screens. How can I show the initial form on the second screen and the other five forms on the main screen?

In matter of window positioning there are no "two screens" but just one "working area".
Meaning if you have two FullHD screens next to each other you have a working area of 3840x1080 (minus some for taskbar and such).
If you then place a window at Left = 200 and Top = 100 it will be placed 200 pixels to the left side of the left screen and if you place it at Left = 2120 and Top = 100 it will be placed at the same position on the right screen.
And for all that to work you need to use StartPosition = FormStartPosition.Manual.

I've used this method, hope it helps you:
public void MaximizeToMonitor(Form frm, int monitorIndex)
{
try
{
Screen screen = Screen.AllScreens[monitorIndex];
if(screen != null)
{
frm.WindowState = FormWindowState.Normal;
var workingArea = screen.WorkingArea;
frm.Left = workingArea.Left + 10;
frm.Top = workingArea.Top + 10;
frm.Width = workingArea.Width + 10;
frm.Height = workingArea.Height + 10;
frm.WindowState = FormWindowState.Maximized;
}
}
catch (Exception ex)
{
MessageBox.Show($"Monitor does not exists. {Environment.NewLine}{ex.Message}");
}
}

Related

Screen coordinates to show form on the right screen

I want to show my form on the screen I'm clicking on.
For this I use a globalhookMouse to get the coordinates of my cursor outside my form. I've two screen (1280x1024 and 1680x1050).
I've tried to put my form if my Cursor.Position.X is lower than one of my resolution but I get higher value.
This is how I hook my form to show
private void GlobalHookMouseDownExt(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Middle)
{
this.Show();
this.TopLevel = true;
}
}
How can I know from which screen I clicked to show my form on the right screen ?
System.Windows.Forms.Screen.AllScreens gives you a lot of information about your screens.
You will see that the X can go negative.
int x = System.Windows.Forms.Cursor.Position.X;
int y = System.Windows.Forms.Cursor.Position.Y;
these will always be the coords of where your cursor is at that moment.
the end result would be something like:
if (Cursor.Position.X > 0)
{
this.Location = new System.Drawing.Point(0,0);
}
else
{
this.Location = new System.Drawing.Point(-1920,0);
}
I hope it helps.

Secondary Monitor shows part of Primary Monitor

I have created a win app, which uses secondary monitor to show images.
I have used the following code to detect and set location of secondary monitor(which is an extended monitor of primary monitor).
public void secondarydisplay()
{
FrmSecondaryDisplay secdis = new FrmSecondaryDisplay();
Screen[] screens = Screen.AllScreens;
secdis.MyBase = this;
this.MySecScreen = secdis;
secdis.Show();
setFormLocation(secdis, screens[1]);
}
private void setFormLocation(Form form, Screen screen)
{
Rectangle bounds = screen.Bounds;
form.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
form.StartPosition = FormStartPosition.Manual;
}
Problem is i am getting this thin 6mm white line on the left most corner of the secondary display. which is nothing but the extension of primary display. how do i make it disapper? on moving the cursor to secondary monitor and click on the screen of secondary monitor this white line disappears. and on moving back the cursor to primary monitor and click on it makes the white line appear on secondary monitor. kindly help me how can i resolve this issue. it looks ugly in secondary mopnitor.
Always prepared the window properties before Show()
public void Secondarydisplay()
{
if (Screen.AllScreens.Count() == 1)
{
return; // No second display
}
var secdis = new FrmSecondaryDisplay();
// Actually you shall use secdis.Show(this) to build the relation of the forms.
// When "this" closes, the second display form closes.
secdis.MyBase = this;
this.MySecScreen = secdis;
// Setup Windows Position before Show()
secdis.StartPosition = FormStartPosition.Manual;
secdis.Location = Screen.AllScreens[1].WorkingArea.Location;
secdis.TopMost = true;
secdis.FormBorderStyle = FormBorderStyle.None;
secdis.WindowState = FormWindowState.Maximized;
secdis.Show(this); // See comment above
}

WPF Borderless window is maximized only to primary screen size

I have a problem with multimonitor system and maximizing my borderless WPF C# .NET 4.0 window. One monitor is 1680x1050 (primary) and the second is 1920x1080 (secondary). When I'm maximizing my window on the primary screen - no problems, even when I switch the order of those two. But every time I'm trying to maximize it on the secondary screen it's being cut off to the size of primary monitor. I see that the window size is given appropriate but this doesn't work.
Getting the size of monitor:
private System.Windows.Forms.Screen GetCurrentScreen()
{
System.Drawing.Point centerPoint = new System.Drawing.Point((int)(Left + Width / 2), (int)(Top + Height / 2));
foreach (System.Windows.Forms.Screen s in System.Windows.Forms.Screen.AllScreens)
{
if (s.Bounds.Contains(centerPoint))
{
return s;
}
}
return null;
}
Maximizing:
private void Maximize
{
if (this.WindowState == WindowState.Normal)
{
var scr = GetCurrentScreen();
//this.MaxHeight = scr.WorkingArea.Height;
//this.MaxWidth = scr.WorkingArea.Width;
if (scr != null)
{
if (scr.Primary)
{
this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
this.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
}
else
{
this.MaxHeight = double.PositiveInfinity; //even ridiculous values don't work
this.MaxWidth = double.PositiveInfinity;
this.Height = scr.WorkingArea.Height; // correct values of 2nd screen
this.Width = scr.WorkingArea.Width;
}
}
else
{
this.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
this.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
}
this.WindowState = WindowState.Maximized;
}
What I get is:
http://imgur.com/ZYzVV9Q,yf7lSfY#1
What I want:
http://imgur.com/ZYzVV9Q,yf7lSfY#0
Thanks
This worked for me last time I had to maximize a window on my secondary screen:
Screen sTwo = Screen.AllScreens[1];
this.Top = sTwo.Bounds.Top;
this.Left = sTwo.Bounds.Left;
this.Width = sTwo.Bounds.Width;
this.Height = sTwo.Bounds.Height;
Make sure you add the reference
using System.Windows.Forms;
And set
AllowsTransparency="True"
in your *.xaml
There is a possibility that some of your code is causing this issue as I cannot replicate it on my two screens... they are both the same size, but if I change the resolution on one, the application still maximises correctly. If you start a new WPF Application and just add
WindowState = "Maximized"
to the Window declaration, do you still have the same problem?
Try to override or correct ArrangeOverride method:
http://msdn.microsoft.com/en-us/library/system.windows.frameworkelement.arrangeoverride.aspx
When overridden in a derived class, positions child elements and
determines a size for a FrameworkElement derived class
Symptoms are similar.

How can I check that a window is fully visible on the user's screen?

Is there a way to check that a WinForm is fully visible on the screen (eg is not out of bounds of the screen?)
I've tried using SystemInformation.VirtualScreen for this, which works great as long as the virtual screen is a rectangle, but as soon as it's not (eg 3 screens in a L shape), SystemInformation.VirtualScreen returns the smallest rectangle containing all the visible pixels (so a window on the upper right corner of the L won't be visible although it's in the virtual screen)
The reason I'm trying to achieve this is that I'd like my program to open its child windows in the last location they were on, but I don't want those window to be out of view if the user changes is setup (eg unplugs the extra screen from his laptop)
Here's how I eventually did it :
bool isPointVisibleOnAScreen(Point p)
{
foreach (Screen s in Screen.AllScreens)
{
if (p.X < s.Bounds.Right && p.X > s.Bounds.Left && p.Y > s.Bounds.Top && p.Y < s.Bounds.Bottom)
return true;
}
return false;
}
bool isFormFullyVisible(Form f)
{
return isPointVisibleOnAScreen(new Point(f.Left, f.Top)) && isPointVisibleOnAScreen(new Point(f.Right, f.Top)) && isPointVisibleOnAScreen(new Point(f.Left, f.Bottom)) && isPointVisibleOnAScreen(new Point(f.Right, f.Bottom));
}
There might be some false positive if the user has a "hole" in his display setup (see example below) but I don't think any of my users will ever be in such a situation :)
[1]
[2][X][3]
Here's how I would do it:
This will move the control (form) inside the Display bounds as close as it can to the original location.
private void EnsureVisible(Control ctrl)
{
Rectangle ctrlRect = ctrl.DisplayRectangle; //The dimensions of the ctrl
ctrlRect.Y = ctrl.Top; //Add in the real Top and Left Vals
ctrlRect.X = ctrl.Left;
Rectangle screenRect = Screen.GetWorkingArea(ctrl); //The Working Area fo the screen showing most of the Ctrl
//Now tweak the ctrl's Top and Left until it's fully visible.
ctrl.Left += Math.Min(0, screenRect.Left + screenRect.Width - ctrl.Left - ctrl.Width);
ctrl.Left -= Math.Min(0, ctrl.Left - screenRect.Left);
ctrl.Top += Math.Min(0, screenRect.Top + screenRect.Height - ctrl.Top - ctrl.Height);
ctrl.Top -= Math.Min(0, ctrl.Top - screenRect.Top);
}
Of course to answer your original question instead of moving the control you could just check if any of the 4 Math.Min's returned something other than 0.
This is my solution. It solves the "hole" problem.
/// <summary>
/// True if a window is completely visible
/// </summary>
static bool WindowAllVisible(Rectangle windowRectangle)
{
int areaOfWindow = windowRectangle.Width * windowRectangle.Height;
int areaVisible = 0;
foreach (Screen screen in Screen.AllScreens)
{
Rectangle windowPortionOnScreen = screen.WorkingArea;
windowPortionOnScreen.Intersect(windowRectangle);
areaVisible += windowPortionOnScreen.Width * windowPortionOnScreen.Height;
if (areaVisible >= areaOfWindow)
{
return true;
}
}
return false;
}
I was trying to do this exact same thing detect if the window opened off screen then accordingly reposition it to the nearest location where it was previously found at. I look all over the internet and nothing worked from all the solutions people offered.
So i took it upon myself to make my own class that does just exactly this and it works 100%.
Here is my code
public static class ScreenOperations
{
public static bool IsWindowOnAnyScreen(Window Window, short WindowSizeX, short WindowSizeY, bool AutoAdjustWindow)
{
var Screen = System.Windows.Forms.Screen.FromHandle(new WindowInteropHelper(Window).Handle);
bool LeftSideTest = false, TopSideTest = false, BottomSideTest = false, RightSideTest = false;
if (Window.Left >= Screen.WorkingArea.Left)
LeftSideTest = true;
if (Window.Top >= Screen.WorkingArea.Top)
TopSideTest = true;
if ((Window.Top + WindowSizeY) <= Screen.WorkingArea.Bottom)
BottomSideTest = true;
if ((Window.Left + WindowSizeX) <= Screen.WorkingArea.Right)
RightSideTest = true;
if (LeftSideTest && TopSideTest && BottomSideTest && RightSideTest)
return true;
else
{
if (AutoAdjustWindow)
{
if (!LeftSideTest)
Window.Left = Window.Left - (Window.Left - Screen.WorkingArea.Left);
if (!TopSideTest)
Window.Top = Window.Top - (Window.Top - Screen.WorkingArea.Top);
if (!BottomSideTest)
Window.Top = Window.Top - ((Window.Top + WindowSizeY) - Screen.WorkingArea.Bottom);
if (!RightSideTest)
Window.Left = Window.Left - ((Window.Left + WindowSizeX) - Screen.WorkingArea.Right);
}
}
return false;
}
}
Usage: ScreenOperations.IsWindowOnAnyScreen(WPFWindow, WPFWindowSizeX, WPFWindowSizeY, true);
this will check if the window is offscreen at all, that being 1 pixel under the taskbar or 1 pixel off the users current monitor.
It detects which monitor the window if on first so it should work with multi-monitors.
this method returns true if the window is on the screen and false if its not.
The last parameter is for auto adjusting the window to the nearest part on the screen for you. if you put false for that parameter it will not adjust the window for you.
So this is a complete WPF solution to this issue, and WinForm converting should be easy if you know how to do it, Change Window to Form and FromHandle(Form.Handle) should work.
Check whether Screen.AllScreens.Any(s => s.WorkingArea.Contains(rect))

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?
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;
}
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));
}
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);
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.
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));
}
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.
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.

Categories

Resources