Form Position (set OnLoad) different when program installed - c#

I have a Windows Forms application that I use the following code to dock it to the lower-right side of the screen when it is launched:
protected override void OnLoad(EventArgs e)
{
var s = Screen.FromPoint(this.Location);
this.Location = new Point(s.WorkingArea.Right - this.Width,
s.WorkingArea.Height - this.Height);
base.OnLoad(e);
}
When I am in Visual Studio debug mode, this works like a charm. When I build an installer and install the application (on the same dev box) and run it, the coordinates are slightly different and the form is not perfectly docked in the corner. So I stuck this in the OnLoad:
MessageBox.Show(this.Location.X + "x" + this.Location.Y);
In development mode it displays 1355x720 but when I install it displays 1365x730
Why the discrepency? Obviously I could just subtract 10 for my code to work but I would like an explanation for this behavior.
Update:
This machine is Windows 8.1 Pro 64-bit with multiple monitors.
It is the form size that is different (not Screen.WorkingArea). In development mode the form size shows 245x140 but when I install it shows 235x130
I am also unable to give the form focus. There is a textbox on the form that receives focus onload. It has the blinking caret, but I cannot type until I physically click on the textbox. This again only happens when I install it; works fine when run from VS. I suspect this is related to the form position going off the screen edge.
The form has TopMost set to True

Related

WinForms: How to fix incorrect scaling of Forms in high-DPI, multi-monitor environments (PerMonitorV2) with different resolution/scaling

In a Winforms app, I followed the general guidance in how-to-write-winforms-code-that-auto-scales-to-system-font-and-dpi-settings and in .Net Framework high-dpi support to enable PerMonitorV2 DPI Scaling. I am using .NET Framework 4.8 on a system post Windows 10 Anniversary Update (1607) to make use of the latest high DPI support features.
The DPI scaling looks great if the app is started on the primary monitor or any monitor with the same scaling as the primary monitor but the scaling is completely wrong if any Form (the main Form of the app or a secondary top level Form) is first shown on a display with different DPI than the primary monitor. For example, if the app is started on a 4k/250% scaling laptop screen (with four other monitors at 1920x1080/100% scaling) then the Form gets displayed at 1:1 scaling on the 4k screen and shows up as a tiny 1 square inch on that screen (with only the Title and MenuBar correctly scaled): Image Showing Bad Scaling.
The issue appears to be caused by the fact that the CurrentAutoScaleDimensions of the Form are not being set correctly in these cases. They appear to be set to the current "dimensions" of the primary screen and not the screen that the Form is being shown on. However, if the Form is first shown on the primary screen and then moved to a screen with different DPI, the CurrentAutoScaleDimensions do get correctly updated to reflect the actual DPI of the destination screen and the Form gets scaled correctly. So, for example, if I set the primary screen to be the 4k/250% screen and then start the app on a 1920x1080/100% screen, the CurrentAutoScaleDimensions (incorrectly) get set to those for the 4k/250% screen and result in the Form being extremely overscaled. But if I start the app on the primary 4k/250% screen, it gets scaled correctly when first shown and then also scales correctly as it is dragged to other monitors (and back). In summary, when a Form is first shown, the CurrentAutoScaleDimensions seem to be always getting set to the primary monitor dimensions and not the dimensions of the screen that the Form is being shown on.
Does anyone know of remedy for this situation?
The best solution I have been able to come up with is to force the application to always start up on the Primary Screen regardless of what screen it was launched from. This seems to fix all issues with initial scaling of the main Form and all subsequent scaling as it is dragged between monitors seems fine:
public Form1()
{
this.Font = SystemFonts.IconTitleFont;
// Force the main Form of the app to always open on the primary screen
// to get scaling to work.
this.Location = Screen.PrimaryScreen.WorkingArea.Location;
this.StartPosition = FormStartPosition.Manual;
InitializeComponent();
...
For secondary Forms generated by the application, I have found that they get scaled correctly if I first show them on the primary screen, then hide and redisplay them on the screen containing the application's main Form (where I want them to be displayed). In some cases, I found it was sufficient to just call f.PerformLayout() rather than actually showing the form on the primary screen, but that did not work in all cases.
private void secondFormToolStripMenuItem_Click(object sender, EventArgs e)
{
FormExtra f = new FormExtra(this);
// First display the Form on the primary screen to make scaling correct
f.StartPosition = FormStartPosition.Manual;
f.Location = Screen.PrimaryScreen.WorkingArea.Location;
f.Show();
// Then hide it and move it where we really want it
f.Hide();
f.StartPosition = FormStartPosition.CenterParent;
f.ShowDialog();
}
This solution is not ideal in that the form briefly flashes on another screen which seems rather kludgy. However, this solution does seem to result in correct scaling of all Forms in the application regardless of what monitor the app is started on. I have tested it on two different multi-monitor configurations so far.

Showing Winforms on dual-screen setup

I have a winforms application in C#, with about 10 forms to navigate through.
On all of them, I have set StartPosition as CenterScreen but I use a laptop with a second screen plugged in.
Now the application starts randomly on one of my screens. Also even if the app is on one screen, MessageBoxes pop up on the second one. How can I set the application to always start at the main screen, the one set as "1" in Windows.
I also want to bind the application to the screen it is showing at so that MessageBoxes would appear on the same screen as the app. Another thing I would like to have is so that new forms would show on the same position as previous forms, not going back to the screen where the application started.
What should I use to control the positions of the forms?
I tried changing StartPosition to CenterParent, but that doesn't seem to change anything.
Try this out on starting page ( first form):
private void MyForm_Load(object sender, EventArgs e)
{
this.Location = Screen.AllScreens[0].WorkingArea.Location;
this.StartPosition = FormStartPosition.CenterScreen;
}
More information here : Showing a Windows form on a secondary monitor?
This question is about showing program on secondary screen. just change 1 index to 0 on arrays if you used answers of that.
Edit:
Just for emphasize Bryce Wagner comment for other people read this question :
If you're calling it from a form or user control, you'll want to call MessageBox.Show(this, "Message") instead.
Combining all answers here and in similar questions, the working solution for showing app on primary screen is this:
private void FormLogin_Load(object sender, EventArgs e)
{
this.Location = Screen.AllScreens[0].WorkingArea.Location;
ReallyCenterToScreen();
}
protected void ReallyCenterToScreen()
{
Screen screen = Screen.FromControl(this);
Rectangle workingArea = screen.WorkingArea;
this.Location = new Point()
{
X = Math.Max(workingArea.X, workingArea.X + (workingArea.Width - this.Width) / 2),
Y = Math.Max(workingArea.Y, workingArea.Y + (workingArea.Height - this.Height) / 2)
};
}
And to keep the MessageBoxes on the center screen is this:
MessageBox.Show(this, "Message")
Sources are the comment of #Bryce Wagner to my question, the answer from #Mohamad Shahrestani and from this question answer by #Sarsur.A
I have a laptop with a second screen. Windows 10 is in "Extend" mode. None of the code examples helped with my dialog ignoring the manual location.
It turns out that NVidia has some helpful options in their driver. One will decide for you where you want your form or your dialog. If your code just doesn't seem to behave, try the "nView Desktop Manager" -> "Windows Manager" -> "Dialog box repositioning" and Open windows on settings.

Windows forms full screen resolution

I started working on a project in Windows Forms, and I want to set my main Form to full screen, and start adding control on it. The problem is that, after I set the Form to FullScreen with
this.WindowState = System.Windows.Forms.FormWindowState.Maximized;
the main form is indeed set to FullScreen, but it remains at the original resolution in Visual Studio IDE. So I tried to get the Form resolution when in Full Screen with this piece of code
int h = Size.Height;
int w = Size.Width;
label1.Text = h.ToString() + " " + w.ToString();
and it indeed returns the resolution of the Form at that moment (1379 x 718) but the main problem is that when I set the Form resolution in IDE to that of the returned code above and then try to place a Control at let's say Position.X = 1300, it will show it halfway across the screen in the main program. It seems that the problem is a Form resolution at FullScreen different than the resolution at which I can place Controls.
Is there a solution to this problem?

Custom TabControl display issues

I've been writing a custom drawn tab control for a few days now and for the most part everything is pretty and it does an amazing job ... except when I use it on my Windows 10 computer (at run-time).
I've gone back to the most basic few lines of code to trace the error and I can't for the life of me figure this out.
Below is the only code being used, in a nutshell I'm designing a horizontal aligned tab control.
using System.Drawing;
using System.Windows.Forms;
namespace WindowsFormsApplication1.UI
{
class TabControlTest : TabControl
{
public TabControlTest()
{
Alignment = TabAlignment.Left;
SizeMode = TabSizeMode.Fixed;
}
}
}
I've simply added the custom tab control to the form, added a couple of group boxes for reference purposes and changed the background colour of the form to grey so you can clearly see the tab control.
Now, at design time the 2 group boxes (1 in the tab control, 1 on the form) align perfectly.
But at run-time I see a very different result.
As you can see the tab part of the control is now larger than it was at design time and the resulting change means the contexts of the tab have also moved.
If I do this on a Windows 7 computer everything is displayed as it appears at design time, as it should!
I've added ImageSize but it makes no difference.
ItemSize = new System.Drawing.Size(30, 150);
I've reinstalled VS on my (Win10) development machine. I'm at a loss to explain why and how to resolve this.
Any/all help would be immensely appreciated.
Looking at your tab width in your comparison images, I believe this is another issue caused by automatic Windows control scaling. I found that it is the dpiAware option is automatically set when it's run from within Visual Studio and then reverts back to the default Windows Scaling that windows Implements when outside Visual Studio.
To prevent that auto-scaling when run outside Visual Studio altogether you need to Notify the OS that you're application is dpiAware by calling the Win32 P/Invoke SetProcessDPIAware() method from within your Main() before Application.Run() is called, like the example below demonstrates. This will let your controls use the native resolution which your designing the coordinates from.
static class Program
{
[System.Runtime.InteropServices.DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
static void Main(string[] args)
{
if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();
Application.Run(new UIMonitor());
}
}
Alternatively, if you want to keep the scaling, you may be able to set the GroupBox location based off the Width of the Tab Control instead of a specific location. (Or by using some combination of Control measurements instead of exact picel placement.)

Replace Windows Shell or Restrict application window size

I'm working on an application for home based users. And this application involves completely replacing windows explorer for a custom application.
I would like to mimic the behavior of the taskbar. For example, when you click the maximize button in Notepad, it does not overlap the taskbar.
I already tried to use the api to AppBar however, AppBar api does not work when windows explorer is not running and other windows overlap my taskbar.
Any idea how I can do this? If I can restrict the size of maximized windows when ever helps me. The problem is that other applications are not always written by me.
I found an example using an win32 api SystemParametersInfo.
This way I can define an area where the other applications will fit and leave an space to my form even if other applications is maximized.
Link on github
public static void MakeNewDesktopArea()
{
// Save current Working Area size
m_rcOldDesktopRect.left = SystemInformation.WorkingArea.Left;
m_rcOldDesktopRect.top = SystemInformation.WorkingArea.Top;
m_rcOldDesktopRect.right = SystemInformation.WorkingArea.Right;
m_rcOldDesktopRect.bottom = SystemInformation.WorkingArea.Bottom;
// Make a new Workspace
WinAPI.RECT rc;
rc.left = SystemInformation.VirtualScreen.Left + 150;
rc.top = SystemInformation.VirtualScreen.Top; // We reserve the 24 pixels on top for our taskbar
rc.right = SystemInformation.VirtualScreen.Right;
rc.bottom = SystemInformation.VirtualScreen.Bottom - 101;
WinAPI.SystemParametersInfo((int)WinAPI.SPI.SPI_SETWORKAREA, 0, ref rc, 0);
}

Categories