I'm trying to set a Windows Form on secondary monitor, as follows:
private void button1_Click(object sender, EventArgs e)
{
MatrixView n = new MatrixView();
Screen[] screens = Screen.AllScreens;
setFormLocation(n, screens[1]);
n.Show();
}
private void setFormLocation(Form form, Screen screen)
{
// first method
Rectangle bounds = screen.Bounds;
form.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
// second method
//Point location = screen.Bounds.Location;
//Size size = screen.Bounds.Size;
//form.Left = location.X;
//form.Top = location.Y;
//form.Width = size.Width;
//form.Height = size.Height;
}
The properties of bounds seem correct, but in both methods I've tried, this maximizes the form on the primary monitor. Any ideas?
this.Location = Screen.AllScreens[1].WorkingArea.Location;
this is the Form reference.
Try setting StartPosition parameter as FormStartPosition.Manual inside your SetFormLocation method.
#Gengi's answer is succinct and works well. If the window is maximised it does not move the window. This snippet solves that (although I suspect the windows "normal" dimensions must be smaller than the new screen dimensions for this to work):
void showOnScreen(int screenNumber)
{
Screen[] screens = Screen.AllScreens;
if (screenNumber >= 0 && screenNumber < screens.Length)
{
bool maximised = false;
if (WindowState == FormWindowState.Maximized)
{
WindowState = FormWindowState.Normal;
maximised = true;
}
Location = screens[screenNumber].WorkingArea.Location;
if (maximised)
{
WindowState = FormWindowState.Maximized;
}
}
}
Are you sure screens[1] is your secondary? Give screens[0] a try. Your code is basically correct.
Ok, I checked, you will have to do it after the Show():
n.Show();
setFormLocation(n, screens[1]);
which gives some unwanted flicker. But you can probably do:
n.SetBounds(-100, -100, 10, 10); // or similar
n.Show();
setFormLocation(n, screens[1]);
To display form on secondary screen:
Screen primaryFormScreen = Screen.FromControl(primaryForm);
//Use this if you are looking for secondary screen that is not primary
Screen secondaryFormScreen = Screen.AllScreens.FirstOrDefault(s => !s.Primary) ?? primaryFormScreen;
//Use this if you are looking for screen that is not being used by specific form
Screen secondaryFormScreen = Screen.AllScreens.FirstOrDefault(s => !s.Equals(primaryFormScreen)) ?? primaryFormScreen;
//Putting the form on the other screen
secondaryForm.Left = secondaryFormScreen.Bounds.Width;
secondaryForm.Top = secondaryFormScreen.Bounds.Height;
//Recommended to use, You can change it back later to the settings you wish
secondaryForm.StartPosition = FormStartPosition.Manual;
secondaryForm.Location = secondaryFormScreen.Bounds.Location;
Point p = new Point(secondaryFormScreen.Bounds.Location.X, secondaryFormScreen.Bounds.Location.Y);
secondaryForm.Location = p;
secondaryForm.Show();
If you are looking forward for a specific screen, you can loop on "Screen.AllScreens" and use the process above.
I used this for an XNA 4 Dual Screen Application (Full Screen XNA Game Window + WinForm)
In the Form_Load() method, place the following code:
var primaryDisplay = Screen.AllScreens.ElementAtOrDefault(0);
var extendedDisplay = Screen.AllScreens.FirstOrDefault(s => s != primaryDisplay) ?? primaryDisplay;
this.Left = extendedDisplay.WorkingArea.Left + (extendedDisplay.Bounds.Size.Width / 2) - (this.Size.Width / 2);
this.Top = extendedDisplay.WorkingArea.Top + (extendedDisplay.Bounds.Size.Height / 2) - (this.Size.Height / 2);
Set form Startup Position property to Manual
public void MoveWindowToProjector ()
{
Rectangle rectMonitor;
// Create New Process
Process objProcess = new Process();
//Get All the screens associated with this Monitor
Screen[] screens = Screen.AllScreens;
// Get Monitor Count
int iMonitorCount = Screen.AllScreens.Length;
// Get Parameters of Current Project
string[] parametros = Environment.GetCommandLineArgs();
// if (parametros.Length > 0)
// {
//objProcess.StartInfo.FileName = parametros[0];
// objProcess.Start();
// }
// Get Window Handle of this Form
IntPtr hWnd = this.Handle;
Thread.Sleep(1000);
if (IsProjectorMode)
{
if (iMonitorCount > 1) // If monitor Count 2 or more
{
//Get the Dimension of the monitor
rectMonitor = Screen.AllScreens[1].WorkingArea;
}
else
{
//Get the Dimension of the monitor
rectMonitor = Screen.AllScreens[0].WorkingArea;
}
}
else
{
rectMonitor = Screen.AllScreens[0].WorkingArea;
}
if (hWnd != IntPtr.Zero)
{
SetWindowPos(hWnd, 0,
rectMonitor.Left, rectMonitor.Top, rectMonitor.Width,
rectMonitor.Height, SWP_SHOWWINDOW);
}
}
This method shows forms on selected screen from left to right:
void ShowFormsOnScreenLeftToRight(Screen screen, params Form[] forms)
{
if (forms == null || forms.Length == 0)
return;
var formsCnt = forms.Length;
var formSize = new Size(screen.WorkingArea.Size.Width / formsCnt, screen.WorkingArea.Size.Height);
for (var i = 0; i < formsCnt; i++)
{
var form = forms[i];
if (form == null)
continue;
form.WindowState = FormWindowState.Normal;
form.Location = new Point(screen.WorkingArea.Left + screen.WorkingArea.Size.Width / formsCnt * i, 0);
form.Size = formSize;
form.BringToFront();
}
}
To solve your problem, you should run:
ShowFormsOnScreenLeftToRight(n, Screen.AllScreens.First(s => !s.Primary));
Screen[] screens = Screen.AllScreens;
sc aoc = new sc();
aoc.Show();
aoc.Location = Screen.AllScreens[INDEX OF YOUR AVAILABLE SCREENS TARGET].WorkingArea.Location;
FOR MAXIMIZED WINDOW STATE
aoc.WindowState = FormWindowState.Maximized;
FOR ANY X,Y POSITION
aoc.Location = new Point(TARGET X POSITION, TARGET Y POSITION);
Related
I have three monitors in the following configuration:
Monitor 1 Monitor 2 Monitor 3
[1280 x 1024] [1200 x 1900] [1280 x 1024]
I use a form to outline a selected monitor (code below), which works great when I initialize or change between Monitors 1 and 3, but results in two rectangles drawn when Monitor 2 is selected :/
I tried to modify the code in many-many different ways, but nothing seems to work. I thought someone might be able to help me understand why two rectangles are being drawn (1280 x 1024 and 1200 x 1900) and how to correct.
Thank you for your time, regards and happy New Year.
P.S. If possible, please keep explanation simple as I am still learning.
public partial class ScreenArea : Form
{
private Pen _pen;
private int screenSelect;
public ScreenArea(int selectScreen = 0)
{
//xInitializeComponent();
TopMost = true;
ShowInTaskbar = true;
FormBorderStyle = FormBorderStyle.None;
BackColor = Color.LightGreen;
TransparencyKey = Color.LightGreen;
_pen = new Pen(Color.Aqua, 5);
Paint += new PaintEventHandler(ScreenArea_Paint);
ScreenSelect = screenSelect;
}
private void ScreenArea_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawRectangle(_pen, 0, 0, Width, Height);
}
public int ScreenSelect
{
get
{
return screenSelect;
}
set
{
Rectangle screenBounds;
try
{
screenBounds = Screen.AllScreens[value].Bounds;
screenSelect = value;
}
catch (Exception)
{
screenBounds = Screen.AllScreens[screenSelect].Bounds;
}
this.Left = screenBounds.X;
this.Top = screenBounds.Y;
this.Width = screenBounds.Width;
this.Height = screenBounds.Height;
}
}
}
Hi below are the simplified code, it's strange that the window stay at the second monitor in a split of second then come back to the first main monitor. There must be a window setting or external program cause it so. Because the same code works in ANOTHER computer with dual screen. And I am sure and double checked that the second monitor is in index 1 : showOnMonitor(1, Q);
Q = new queue();
showOnMonitor(1, Q);
Q.Show();
public static void showOnMonitor(int monitor, Window w2)
{
Screen[] sc;
sc = Screen.AllScreens;
if ( monitor >= sc.Length )
{
monitor = 0;
}
w2.WindowStartupLocation = WindowStartupLocation.Manual;
var workingArea = sc[monitor].WorkingArea;
w2.Left = workingArea.Left;
w2.Top = workingArea.Top;
w2.Width = workingArea.Width;
w2.Height = workingArea.Height;
}
Okay, I don't know why this works. But it's the solution.
Q = new queue();
Q.Show();
Thread.Sleep( 100 ); //need to delay first before moving the position
showOnMonitor(1, Q);
public static void showOnMonitor(int monitor, Window w2)
{
Screen[] sc;
sc = Screen.AllScreens;
if ( monitor >= sc.Length )
{
monitor = 0;
}
w2.WindowStartupLocation = WindowStartupLocation.Manual;
var workingArea = sc[monitor].WorkingArea;
w2.Left = workingArea.Left;
w2.Top = workingArea.Top;
w2.Width = workingArea.Width;
w2.Height = workingArea.Height;
}
I am developing a Windows desktop application dual monitor where I need to display my form sometimes on primary screen and sometimes on secondary,
which works fine but when I display it on my secondary screen I want it to be displayed on centre of my screen which is not working.
Here is my code:
if (Screen.AllScreens.Length > 1)
myForm.Location = Screen.AllScreens[1].WorkingArea.Location;
myForm.StartPosition = FormStartPosition.Manual; // because i wrote manual it is displayed on Top left of my secondaryScreen which is ok
myForm.show();
but I want to diplay it on centre so I wrote
myForm.StartPosition = FormStartPosition.CentreScreen;
//it is not working again a form is displayed on Centre of PrimaryScreen..
Any idea why?
You cannot use StartPosition.CenterScreen because that picks the monitor on which the mouse is currently located. Usually desirable but not what you are asking for. You must use the form's Load event to move it where you want it. Using form's Load is important, you do not know the size of the window until after it is created and the user's preferences are applied and it is rescaled to match the video DPI.
Boilerplate code should look like this:
private void button1_Click(object sender, EventArgs e) {
var form = new Form2();
form.Load += CenterOnSecondMonitor;
form.Show();
}
private void CenterOnSecondMonitor(object sender, EventArgs e) {
var form = (Form)sender;
var area = Screen.AllScreens.Length > 1 ? Screen.AllScreens[1].WorkingArea : Screen.PrimaryScreen.WorkingArea;
form.Location = new Point((area.Width - form.Width) / 2, (area.Height - form.Height) / 2);
form.Load -= CenterOnSecondMonitor;
}
Or you put this code into the form itself, the more common choice:
protected override void OnLoad(EventArgs e) {
var area = Screen.AllScreens.Length > 1 ? Screen.AllScreens[1].WorkingArea : Screen.PrimaryScreen.WorkingArea;
this.Location = new Point((area.Width - this.Width) / 2, (area.Height - this.Height) / 2);
base.OnLoad(e);
}
look for the property of your winform named StartPosition then set it into Center Screen
You could write an extension method:
public static void MoveForm(this Form form, Screen screen = null)
{
if(screen == null)
{
//If we have a single screen, we are not moving the form
if(Screen.AllScreens.Length > 1) return;
screen = Screen.AllScreens[1];
}
var bounds = screen.Bounds;
form.Left = ((bounds.Left + bounds.Right) / 2) - (form.Width / 2);
form.Top = ((bounds.Top + bounds.Bottom) / 2) - (form.Height / 2);
}
private void CenterOnTheCurrentScreen()
{
Rectangle workingArea = Screen.FromControl(this).WorkingArea;
Point center = new Point((workingArea.Width - this.Width) / 2, (workingArea.Height - this.Height) / 2);
this.Location = new Point(workingArea.X + center.X, workingArea.Y + center.Y);
}
I have a situation where it would be beneficial to me to allow my windows form to be resized by the user, but only vertically. After some searching, it seems like there isn't much on this particular subject. Is it possible?
You need to set the form's MinimumSize and MaximumSize properties to two sizes with different heights but equal widths.
If you don't want the horizontal resize cursor to appear at all, you'll need to handle the WM_NCHITTEST message, like this:
protected override void WndProc(ref Message m) {
base.WndProc(ref m);
switch (m.Msg) {
case 0x84: //WM_NCHITTEST
var result = (HitTest)m.Result.ToInt32();
if (result == HitTest.Left || result == HitTest.Right)
m.Result = new IntPtr((int)HitTest.Caption);
if (result == HitTest.TopLeft || result == HitTest.TopRight)
m.Result = new IntPtr((int)HitTest.Top);
if (result == HitTest.BottomLeft || result == HitTest.BottomRight)
m.Result = new IntPtr((int)HitTest.Bottom);
break;
}
}
enum HitTest {
Caption = 2,
Transparent = -1,
Nowhere = 0,
Client = 1,
Left = 10,
Right = 11,
Top = 12,
TopLeft = 13,
TopRight = 14,
Bottom = 15,
BottomLeft = 16,
BottomRight = 17,
Border = 18
}
Just an idea...
public partial class Form1 : Form {
int _width;
public Form1() {
_width = this.Width;
InitializeComponent();
}
protected override void OnResize(EventArgs e) {
this.Width = _width;
base.OnResize(e);
}
}
EDIT: please note that the min/max size solutions work much better than this hack :)
Set the max & min size for the width of the form only.
Let the FormBorderStyle to Resizable and set MaximumSize and MinimumSize = new Size(this.Width, 0)
Correction:
this.MinimumSize = new Size(this.Width, 0);
this.MaximumSize = new Size(this.Width, Int32.MaxValue);
Yes, it is possible. Just set your form.MinimumSize.Width = form.MaximumSize.Width = 100 (or whatever width you want).
To avoid the "rubber-banding" effect of #orsogufo's solution:
public Form1()
{
InitializeComponent();
this.MinimumSize = new Size(500, 0);
this.MaximumSize = new Size(500, Screen.AllScreens.Max(s => s.Bounds.Height));
}
It won't correctly adjust its maximum height to accommodate a larger screen if you resize the screen bounds, but for static screen sizes it works great.
I'm trying to set a Windows Form on secondary monitor, as follows:
private void button1_Click(object sender, EventArgs e)
{
MatrixView n = new MatrixView();
Screen[] screens = Screen.AllScreens;
setFormLocation(n, screens[1]);
n.Show();
}
private void setFormLocation(Form form, Screen screen)
{
// first method
Rectangle bounds = screen.Bounds;
form.SetBounds(bounds.X, bounds.Y, bounds.Width, bounds.Height);
// second method
//Point location = screen.Bounds.Location;
//Size size = screen.Bounds.Size;
//form.Left = location.X;
//form.Top = location.Y;
//form.Width = size.Width;
//form.Height = size.Height;
}
The properties of bounds seem correct, but in both methods I've tried, this maximizes the form on the primary monitor. Any ideas?
this.Location = Screen.AllScreens[1].WorkingArea.Location;
this is the Form reference.
Try setting StartPosition parameter as FormStartPosition.Manual inside your SetFormLocation method.
#Gengi's answer is succinct and works well. If the window is maximised it does not move the window. This snippet solves that (although I suspect the windows "normal" dimensions must be smaller than the new screen dimensions for this to work):
void showOnScreen(int screenNumber)
{
Screen[] screens = Screen.AllScreens;
if (screenNumber >= 0 && screenNumber < screens.Length)
{
bool maximised = false;
if (WindowState == FormWindowState.Maximized)
{
WindowState = FormWindowState.Normal;
maximised = true;
}
Location = screens[screenNumber].WorkingArea.Location;
if (maximised)
{
WindowState = FormWindowState.Maximized;
}
}
}
Are you sure screens[1] is your secondary? Give screens[0] a try. Your code is basically correct.
Ok, I checked, you will have to do it after the Show():
n.Show();
setFormLocation(n, screens[1]);
which gives some unwanted flicker. But you can probably do:
n.SetBounds(-100, -100, 10, 10); // or similar
n.Show();
setFormLocation(n, screens[1]);
To display form on secondary screen:
Screen primaryFormScreen = Screen.FromControl(primaryForm);
//Use this if you are looking for secondary screen that is not primary
Screen secondaryFormScreen = Screen.AllScreens.FirstOrDefault(s => !s.Primary) ?? primaryFormScreen;
//Use this if you are looking for screen that is not being used by specific form
Screen secondaryFormScreen = Screen.AllScreens.FirstOrDefault(s => !s.Equals(primaryFormScreen)) ?? primaryFormScreen;
//Putting the form on the other screen
secondaryForm.Left = secondaryFormScreen.Bounds.Width;
secondaryForm.Top = secondaryFormScreen.Bounds.Height;
//Recommended to use, You can change it back later to the settings you wish
secondaryForm.StartPosition = FormStartPosition.Manual;
secondaryForm.Location = secondaryFormScreen.Bounds.Location;
Point p = new Point(secondaryFormScreen.Bounds.Location.X, secondaryFormScreen.Bounds.Location.Y);
secondaryForm.Location = p;
secondaryForm.Show();
If you are looking forward for a specific screen, you can loop on "Screen.AllScreens" and use the process above.
I used this for an XNA 4 Dual Screen Application (Full Screen XNA Game Window + WinForm)
In the Form_Load() method, place the following code:
var primaryDisplay = Screen.AllScreens.ElementAtOrDefault(0);
var extendedDisplay = Screen.AllScreens.FirstOrDefault(s => s != primaryDisplay) ?? primaryDisplay;
this.Left = extendedDisplay.WorkingArea.Left + (extendedDisplay.Bounds.Size.Width / 2) - (this.Size.Width / 2);
this.Top = extendedDisplay.WorkingArea.Top + (extendedDisplay.Bounds.Size.Height / 2) - (this.Size.Height / 2);
Set form Startup Position property to Manual
public void MoveWindowToProjector ()
{
Rectangle rectMonitor;
// Create New Process
Process objProcess = new Process();
//Get All the screens associated with this Monitor
Screen[] screens = Screen.AllScreens;
// Get Monitor Count
int iMonitorCount = Screen.AllScreens.Length;
// Get Parameters of Current Project
string[] parametros = Environment.GetCommandLineArgs();
// if (parametros.Length > 0)
// {
//objProcess.StartInfo.FileName = parametros[0];
// objProcess.Start();
// }
// Get Window Handle of this Form
IntPtr hWnd = this.Handle;
Thread.Sleep(1000);
if (IsProjectorMode)
{
if (iMonitorCount > 1) // If monitor Count 2 or more
{
//Get the Dimension of the monitor
rectMonitor = Screen.AllScreens[1].WorkingArea;
}
else
{
//Get the Dimension of the monitor
rectMonitor = Screen.AllScreens[0].WorkingArea;
}
}
else
{
rectMonitor = Screen.AllScreens[0].WorkingArea;
}
if (hWnd != IntPtr.Zero)
{
SetWindowPos(hWnd, 0,
rectMonitor.Left, rectMonitor.Top, rectMonitor.Width,
rectMonitor.Height, SWP_SHOWWINDOW);
}
}
This method shows forms on selected screen from left to right:
void ShowFormsOnScreenLeftToRight(Screen screen, params Form[] forms)
{
if (forms == null || forms.Length == 0)
return;
var formsCnt = forms.Length;
var formSize = new Size(screen.WorkingArea.Size.Width / formsCnt, screen.WorkingArea.Size.Height);
for (var i = 0; i < formsCnt; i++)
{
var form = forms[i];
if (form == null)
continue;
form.WindowState = FormWindowState.Normal;
form.Location = new Point(screen.WorkingArea.Left + screen.WorkingArea.Size.Width / formsCnt * i, 0);
form.Size = formSize;
form.BringToFront();
}
}
To solve your problem, you should run:
ShowFormsOnScreenLeftToRight(n, Screen.AllScreens.First(s => !s.Primary));
Screen[] screens = Screen.AllScreens;
sc aoc = new sc();
aoc.Show();
aoc.Location = Screen.AllScreens[INDEX OF YOUR AVAILABLE SCREENS TARGET].WorkingArea.Location;
FOR MAXIMIZED WINDOW STATE
aoc.WindowState = FormWindowState.Maximized;
FOR ANY X,Y POSITION
aoc.Location = new Point(TARGET X POSITION, TARGET Y POSITION);