WPF 中关于 Screen 的问题(主副屏)
WPF 及 Winform 的 PrimaryScreen 不同用法
https://blog.csdn.net/wzhiu/article/details/7187291
WPF:
this.Top = System.Windows.SystemParameters.WorkArea.Height - this.Height; this.Left = System.Windows.SystemParameters.WorkArea.Width - this.Width;
Winform:
this.Top = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Height - this.Height; this.Left = System.Windows.Forms.Screen.PrimaryScreen.WorkingArea.Width - this.Width;
Show and Maximize WPF window on a specific screen
Question:
I'm using the following method to display a WPF Window on a specific screen:
private void ShowOnMonitor(int monitor,Window window) { Screen[] screens = Screen.AllScreens; window.WindowStyle = WindowStyle.None; window.WindowStartupLocation = WindowStartupLocation.Manual; window.Left = screens[monitor].Bounds.Left; window.Top = screens[monitor].Bounds.Top; //window.WindowState = WindowState.Maximized; window.Show(); }
The problem is I need the Window to be Maximized to fill the whole screen but as soon as I set:
window.WindowState = WindowState.Maximized;
It keeps showing the Window Maximized but only on the first screen no matter what number I pass through to the ShowOnMonitor() method.
Replies
1. Found the answer for this problem from the below link
http://mostlytech.blogspot.in/2008/01/maximizing-wpf-window-to-second-monitor.html
We cannot maximize the window until the window is loaded when using multiple screens. so hook up a window loaded event and set the window state to Maximized.
private void ShowOnMonitor(int monitor, Window window) { var screen = ScreenHandler.GetScreen(monitor); var currentScreen = ScreenHandler.GetCurrentScreen(this); window.WindowState = WindowState.Normal; window.Left = screen.WorkingArea.Left; window.Top = screen.WorkingArea.Top; window.Width = screen.WorkingArea.Width; window.Height = screen.WorkingArea.Height; window.Loaded += Window_Loaded; } /*You can use this event for all the Windows*/ private void Window_Loaded(object sender, RoutedEventArgs e) { var senderWindow = sender as Window; senderWindow.WindowState = WindowState.Maximized; }
ScreenHandler.cs
public static class ScreenHandler { public static Screen GetCurrentScreen(Window window) { var parentArea = new System.Drawing.Rectangle((int)window.Left, (int)window.Top, (int)window.Width, (int)window.Height); return Screen.FromRectangle(parentArea); } public static Screen GetScreen(int requestedScreen) { var screens = Screen.AllScreens; var mainScreen = 0; if (screens.Length > 1 && mainScreen < screens.Length) { return screens[requestedScreen]; } return screens[0]; } }
2. I found another post on MSDN which also works:
private void ShowOnMonitor(int monitor,Window window) { Screen[] screens = Screen.AllScreens; window.WindowStyle = WindowStyle.None; window.WindowStartupLocation = WindowStartupLocation.Manual; window.Left = screens[monitor].Bounds.Left; window.Top = screens[monitor].Bounds.Top; window.SourceInitialized += (snd, arg) => window.WindowState = WindowState.Maximized; window.Show(); }
3. I am running into what I'm sure is a problem with an obvious solution but where do I run ShowOnMonitor(monitor,window)? after InitializeComponent() in the MainWindow() class function but that doesn't seem to be the case. I thought I would just need to run ShowOnMonitor(0,MainWindow); but it's saying 'MainWindow is a type not a variable' which is true, so I'm not sure how to access to the current MainWindow.
EDIT:
Found the solution. 'this' is the window to pass. ShowOnMonitor(0,this);
Also I tweaked ScreenHandler.cs:
if (screens.Length > 1 && mainScreen < screens.Length) { if (screens.Length > requestedScreen) { return screens[requestedScreen]; } else { return screens[screens.Length - 1]; } }
This conditional ensures that the requested monitor is within bounds and avoids a 'dumb' crash in case a config xml or startup flag is malformed.
How to get the size of the current screen in WPF?
https://stackoverflow.com/questions/1927540/how-to-get-the-size-of-the-current-screen-in-wpf
Question:
I know I can get the size of the primary screen by using
System.Windows.SystemParameters.PrimaryScreenWidth;
System.Windows.SystemParameters.PrimaryScreenHeight;
But how do I get the size of the current screen? (Multi-Screen users do not always use the primary screen and not all screens are using the same resolution, right?)
It would be nice to be able to acces the size from XAML, but doing so from code (C#) would suffice.
Answer:
1. I created a little wrapper around the Screen from System.Windows.Forms, currently everything works... Not sure about the "device independent pixels", though.
public class WpfScreen { public static IEnumerable<WpfScreen> AllScreens() { foreach (Screen screen in System.Windows.Forms.Screen.AllScreens) { yield return new WpfScreen(screen); } } public static WpfScreen GetScreenFrom(Window window) { WindowInteropHelper windowInteropHelper = new WindowInteropHelper(window); Screen screen = System.Windows.Forms.Screen.FromHandle(windowInteropHelper.Handle); WpfScreen wpfScreen = new WpfScreen(screen); return wpfScreen; } public static WpfScreen GetScreenFrom(Point point) { int x = (int) Math.Round(point.X); int y = (int) Math.Round(point.Y); // are x,y device-independent-pixels ?? System.Drawing.Point drawingPoint = new System.Drawing.Point(x, y); Screen screen = System.Windows.Forms.Screen.FromPoint(drawingPoint); WpfScreen wpfScreen = new WpfScreen(screen); return wpfScreen; } public static WpfScreen Primary { get { return new WpfScreen(System.Windows.Forms.Screen.PrimaryScreen); } } private readonly Screen screen; internal WpfScreen(System.Windows.Forms.Screen screen) { this.screen = screen; } public Rect DeviceBounds { get { return this.GetRect(this.screen.Bounds); } } public Rect WorkingArea { get { return this.GetRect(this.screen.WorkingArea); } } private Rect GetRect(Rectangle value) { // should x, y, width, height be device-independent-pixels ?? return new Rect { X = value.X, Y = value.Y, Width = value.Width, Height = value.Height }; } public bool IsPrimary { get { return this.screen.Primary; } } public string DeviceName { get { return this.screen.DeviceName; } } }
2. As far as I know there is no native WPF function to get dimensions of the current monitor. Instead you could PInvoke native multiple display monitors functions, wrap them in managed class and expose all properties you need to consume them from XAML.
WPF: Multiple screens
https://stackoverflow.com/questions/17859414/wpf-multiple-screens
Question:
I'm writing a screensaver in WPF. I have the screensaver working, however, it only displays on my main monitor. Is there a way to "black out" or draw graphics to additional monitors when the user has multiple displays? I've done some searching around, but haven't found anything relevant.
UPDATE:
From ananthonline's answer below, I was able to accomplish the "black out" effect on non-primary displays using the following window:
<Window x:Class="ScreenSaver.BlackOut" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Cursor="None" WindowStyle="None" ResizeMode="NoResize" Background="Black"> </Window>
and initializing one for each screen in App.xaml.cs
using the following process:
foreach (Screen s in Screen.AllScreens) { if (s != Screen.PrimaryScreen) { BlackOut blackOut = new BlackOut(); blackOut.Top = s.WorkingArea.Top; blackOut.Left = s.WorkingArea.Left; blackOut.Width = s.WorkingArea.Width; blackOut.Height = s.WorkingArea.Height; blackOut.Show(); } }
Note an import to System.Windows.Forms
is required to access the Screen
class.
Answer:
You should be able to use the System.Drawing.Screen.* classes to set up multiple windows on each screen. Mind that you don't set each window to be maximized, but a properly sized, border less window.
Also - you might want to remember that the total bounds of the multi monitor setup may not always be a rectangle (if you plan to "union" all the bounds to create a window spanning all monitors).