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).

原文地址:https://www.cnblogs.com/xiefang2008/p/9594104.html

时间: 2024-08-02 21:45:56

WPF 中关于 Screen 的问题(主副屏)的相关文章

WPF中嵌入普通Win32程序的方法

公司现在在研发基于.Net中WPF技术的产品,由于要兼容旧有产品,比如一些旧有的Win32程序.第三方的Win32程序等等,还要实现自动登录这些外部Win32程序,因此必须能够将这些程序整合到我们的系统中来,让使用者看起来它们好像是一个程序. 在MSDN中有专门的章节提到了在WPF中嵌入Win32控件的办法,那就是使用 HwndHost ,只要把 Win32控件的句柄传递给 HwndHost 就可以了.MSDN中的例子演示的都是在同一个进程内创建的 Win32控件,我一开始认为只要通过FindW

WPF中实现先登录后启动主程序的方法

[转载] http://blog.csdn.net/swarb/article/details/17301167 WPF中实现先登录后启动主程序的方法 我觉得先登录后启动应用主程序是一个很经典的问题,基本上如果要写一个应用程序都会用到这个的小环节.我在这个问题上挣扎了大半天才找到解决方案,我的实现方法我觉得有点不正宗,如果有哪位高手知道更好的方法欢迎留言指导!! 首先来说一下传统C#在WinForm中的实现方法,基本上是在Main函数中根据第一个启动窗口的DialogResult来判断是否实例第

WPF中DPI的问题

先搞清楚一下几个概念: DPI:dots  per  inch ,每英寸的点数.我们常说的鼠标DPI,是指鼠标移动一英寸的距离滑过的点数:打印DPI,每英寸的长度打印的点数:扫描DPI,每英寸扫描了多少个点.(更多请参考百度百科http://baike.baidu.com/view/49853.htm) 像素:pixel,picute和element的缩写.像素可以简单的理解为DPI里面的点.例如,显示器的分辨率为1024像素*768像素,就是说显示器的横向可显示1024个点(像素),纵向科研可

【转】WPF中实现自定义虚拟容器(实现VirtualizingPanel)

在WPF应用程序开发过程中,大数据量的数据展现通常都要考虑性能问题.有下面一种常见的情况:原始数据源数据量很大,但是某一时刻数据容器中的可见元素个数是有限的,剩余大多数元素都处于不可见状态,如果一次性将所有的数据元素都渲染出来则会非常的消耗性能.因而可以考虑只渲染当前可视区域内的元素,当可视区域内的元素需要发生改变时,再渲染即将展现的元素,最后将不再需要展现的元素清除掉,这样可以大大提高性能.在WPF中System.Windows.Controls命名空间下的VirtualizingStackP

WPF中的换行符

原文:WPF中的换行符 WPF中UI上和后台代码中的换行符不同. 其中: XAML中为 C#代码中为 \r\n 或者: Environment.NewLine 版权声明:本文为博主原创文章,未经博主允许不得转载.

WPF中动态更新TextBlock文字中的超链接,文本

1.------------------------------------------------------------------------- 修改超链接的文本文字: <TextBlock><Hyperlink> <TextBlock  x:Name="TextBlockNeedChange" Text="改变的文本" /> </Hyperlink></TextBlock> 修改TextBlockN

Wpf中MediaElement循环播放

原文:Wpf中MediaElement循环播放 前一段时间做了一个项目,里面牵涉到媒体文件的循环播放问题,在网上看了好多例子,都是在xaml中添加为MediaElement添加一个TimeLine,不符合我的项目需求,就自己想了一个办法,基本的思路就是在媒体播放完毕后再次Play一下就OK了,废话不多说,首先Show一下我的代码吧: 写一个方法用来动态创建一个MediaElement:这里的ScreenModel是我创建的一个类,大家根据需要可以修改 MediaElement MediaElem

WinForm和WPF中注册热键

由于.Net没有提供专门的类库处理热键,所以需要直接调用windows API来解决. HotKey为.NET调用Windows API的封装代码,主要是RegisterHotKey和UnregisterHotKey class HotKey { /// <summary> /// 如果函数执行成功,返回值不为0. /// 如果函数执行失败,返回值为0.要得到扩展错误信息,调用GetLastError..NET方法:Marshal.GetLastWin32Error() /// </su

在 WPF 中的线程

线程处理使程序能够执行并发处理,以便它可以做多个操作一次.节省开发人员从线程处理困难的方式,设计了 WPF (窗口演示文稿基金会).这篇文章可以帮助理解线程在 WPF 中的正确用法. WPF 内部线程和规则 所有 WPF 应用程序中都运行两个线程: 为呈现-它在后台运行,所以,它被隐藏. 用于管理 UI 界面 (UI 线程) — — 大多数 WPF 对象与 UI 线程被束缚.它接收输入. 绘制屏幕. 运行的代码和处理事件. WPF 支持单线程单元模型,有以下规则: 一个线程在整个应用程序中运行,