How to show SplashScreen on the second monitor? Now it shows only on primary monitor, but application starts on the secondary monitor.
There are no properties to control where the standard WPF splash screen shows up.
If you need to change the default behavior you need to do your own implementation. An example is available here
You can use the 'Screen' class with the WindowStartupLocation property of your splash screen (I assume you are using a Window for this).
Like:
Window someWindow = new SomeWindow();
someWindow.WindowStartupLocation = WindowStartupLocation.Manual;
someWindow.Left = Screen.AllScreens[1].Bounds.Left;
someWindow.Top = Screen.AllScreens[1].Bounds.Top;
If needed you can center it yourself ofcourse. Take the screen height and the window height and calculate the center.
Check out the System.Windows.Forms.Screen class.
You can use Screen.GetWorkingArea() to get the current display, and then set the location of the splash screen based on that. Screen.FromControl() and Screen.AllScreens may also be useful.
Related
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.
How to show a box in the taskbar?In the Forms i have added the image, but how can I show in the taskbar at the bottom right?
Like This:
Example:
You probably want to look into the NotifyIcon Class, since you are talking about the Task Bar.
For your notification form, you would target the primary screens lower right corner:
Something like this:
notifyForm.Location = new Point(Screen.PrimaryScreen.WorkingArea.Width - notifyForm.Width,
Screen.PrimaryScreen.WorkingArea.Height - notifyForm.Height);
Make sure your notification has the following property set:
notifyForm.StartPosition = FormStartPosition.Manual;
Just set its position to bottom right... assuming that is where the notification area is for every user...
I want to make a program to display information while I'm in another full screen application.
Something like: show what song is playing(from Winamp) while in Starcraft II.
How would I got about doing that?
I would start by creating a new window with the topmost flag set. I think that will do what you want. You might have to manually move that window to the top of the topmost z order with a call to SetWindowPos. (SetWindowPos is a win32 call, but you can pInvoke it from C# if needed.)
I have a C# Windows application that I want to ensure will show up on a second monitor if the user moves it to one. I need to save the main form's size, location and window state - which I've already handled - but I also need to know which screen it was on when the user closed the application.
I'm using the Screen class to determine the size of the current screen but I can't find anything on how to determine which screen the application was running on.
Edit: Thanks for the responses, everyone! I wanted to determine which monitor the window was on so I could do proper bounds checking in case the user accidentally put the window outside the viewing area or changed the screen size such that the form wouldn't be completely visible anymore.
You can get an array of Screens that you have using this code.
Screen[] screens = Screen.AllScreens;
You can also figure out which screen you are on, by running this code (this is the windows form you are on)
Screen screen = Screen.FromControl(this); //this is the Form class
in short check out the Screen class and static helper methods, they might help you.
MSDN Link, doesn't have much..I suggest messing around in the code by yourself.
If you remember the window's location and size, that will be enough. When you set the position to the previously used position, if it happened to be on the second monitor it will go back there.
For example, if you have 2 monitors, both sized 1280x1024 and you set your window's left position to be 2000px, it will appear on the second monitor (assuming the second monitor is to the right of the first.) :)
If you are worried about the second monitor not being there when the application is started the next time, you can use this method to determine if your window intersects any of the screens:
private bool isWindowVisible(Rectangle rect)
{
foreach (Screen screen in Screen.AllScreens)
{
if (screen.Bounds.IntersectsWith(rect))
return true;
}
return false;
}
Just pass in your window's desired location and it will tell you if it will be visible on one of the screens. Enjoy!
You can get the current Screen with
var s = Screen.FromControl(this);
where this is the Form (or any control on the Form). As about how to remember that is a little tricky, but I would go for the index in the Screen.AllScreens array, or maybe s.DeviceName. In either case, check before using the settings on startup, to prevent using a monitor that was disconnected.
The location of the form will tell you which screen the form is on. I don't really understand why you'd need to know what screen it is on, because if you restore it using the location you saved it should just restore to the same location (maybe you can expand as to why).
Otherwise you can do something like this:
Screen[] scr = Screen.AllScreens;
scr[i].Bounds.IntersectsWith(form.Bounds);
Each screen has a Bounds property which returns a Rectangle. You can use the IntersectsWith() function to determine if the form is within the screen.
Also, they basically provide a function that does this as well on the Screen class
Screen screen = Screen.FromControl(form);
You can use the 'Screen' object:
System.Windows.Forms.Screen
Start playing with something like this:
Screen[] screens = Screen.AllScreens;
for (int i = 0; i < screens.Length ; i++)
{
Debug.Print(screens[i].Bounds.ToString());
Debug.Print(screens[i].DeviceName);
Debug.Print(screens[i].WorkingArea.ToString());
}
It may get you what you need
So I have two forms, mainform and extraform.
extraform is set always moved to the right of mainform when mainform initializes
Sometimes mainform takes up both monitors and extraform is pushed off the screen never to be seen again. I would like to prevent this if possible. How can I do so? It must support dual monitors, that may or may not have distance between them (i.e. screen 1 is 20px to the left of screen 2).
How can I do this?
You can use the Screen class to work out where your window is relative to the desktop. The Screen class has a FromRectangle method, so you can figure out which screen you should be positioning your Form on (by passing your form's Bounds property in).
Each Screen object has a Bounds property, which you can use to compare to the location and size of your window, and adjust them accordingly.
It depends what you want should happen when extraform is pushed beyond the bounds of the screen(s).
However, to find out whether or not it's being pushed off, it's quite simple using the System.Windows.Forms.Screens class. Then you can do bounds checking like so:
foreach (var screen in Screen.AllScreens)
{
if(screen.Bounds.Contains(this.Bounds))
{
Console.WriteLine("Device "+screen.DeviceName+" contains form!");
}
}
Code assumes being in a form. Note that this code only prints that a screen contains the form if the form is completely contained on the screen. But this should be rather simple to fix, depending on your needs.
Perhaps the DesktopLocation property in your Forms can give you a clue about what's happening with what's happening with them