如何确定 WPF 窗口所在的显示器

52
在C#应用程序中,我如何确定一个WPF窗口是在主监视器还是另一个监视器中?

1
很有可能会同时出现在两个平台上。 - Hans Passant
5
@Helen那个问题适用于Winforms,而这是针对不同的WPF。 - Chris Zeh
7个回答

36

如果窗口被最大化,那么你不能完全依赖window.Left或者window.Top,因为它们可能是窗口最大化之前的坐标。但是在所有情况下,你可以采用以下方法:

    var screen = System.Windows.Forms.Screen.FromHandle(
       new System.Windows.Interop.WindowInteropHelper(window).Handle);

13
我看到的是之前打开的屏幕,而不是当前的。 - Coneone

11

目前其他回复似乎并未涉及到问题中的WPF部分,以下是我的见解:

与其他回复中提到的Windows Forms的Screen类所包含的详细屏幕信息不同,WPF似乎没有暴露这方面的内容。

不过,在WPF程序中,您可以使用WinForms的Screen类:

在程序中添加对System.Windows.FormsSystem.Drawing的引用即可。

var screen = System.Windows.Forms.Screen.FromRectangle(
  new System.Drawing.Rectangle(
    (int)myWindow.Left, (int)myWindow.Top, 
    (int)myWindow.Width, (int)myWindow.Height));

请注意,如果您是一个苛刻的人,您可能会注意到,在某些情况下,双精度转整数的代码可能会导致右侧和底部坐标偏移一个像素。但由于您是一个苛刻的人,您将非常乐意修复我的代码;-)

3
它也不能与非默认 DPI 一起使用,特别是不同的每个监视器 DPI。 - LOST

7
为了实现这一点,您需要使用一些本地方法。

https://msdn.microsoft.com/en-us/library/windows/desktop/dd145064(v=vs.85).aspx

internal static class NativeMethods
{
    public const Int32 MONITOR_DEFAULTTOPRIMARY = 0x00000001;
    public const Int32 MONITOR_DEFAULTTONEAREST = 0x00000002;

    [DllImport( "user32.dll" )]
    public static extern IntPtr MonitorFromWindow( IntPtr handle, Int32 flags );
}

然后,您只需检查窗口在哪个显示器上以及哪个是主要显示器。如下:

        var hwnd = new WindowInteropHelper( this ).EnsureHandle();
        var currentMonitor = NativeMethods.MonitorFromWindow( hwnd, NativeMethods.MONITOR_DEFAULTTONEAREST );
        var primaryMonitor = NativeMethods.MonitorFromWindow( IntPtr.Zero, NativeMethods.MONITOR_DEFAULTTOPRIMARY );
        var isInPrimary = currentMonitor == primaryMonitor;

1
R.Rusev 这个返回的是显示器的 hwnd 吗? 那么如何使用该 hwnd 知道它是哪个显示器的呢? 我的意思是 Windows 在显示配置中显示的数字。 有没有一种方法可以获取该数字并知道我的 WPF 窗口在哪个显示器上运行? - MrBi

1
public static bool IsOnPrimary(Window myWindow)
{
    var rect = myWindow.RestoreBounds;
    Rectangle myWindowBounds= new Rectangle((int)rect.X, (int)rect.Y, (int)rect.Width, (int)rect.Height);
    return myWindowBounds.IntersectsWith(WinForms.Screen.PrimaryScreen.Bounds);

    /* Where
        using System.Drawing;
        using System.Windows;
        using WinForms = System.Windows.Forms;
     */
}

请注意,如果窗口在屏幕左侧或右侧停靠(使用Windows键+箭头左或右),则myWindow.RestoreBounds不会返回窗口的真实大小和位置。在这种情况下,您应该使用myWindow.LeftmyWindow.RightmyWindow.WidthmyWindow.Height - René

0
你可以使用这段代码:
if (Screen.AllScreens.Length < 2)
{
    Console.WriteLine("You have just one monitor!");
    return;
}

string primaryMonitor = "";
string currentMonitor = Screen.FromHandle(new WindowInteropHelper(this).Handle).DeviceName;

for (int i = 0; i < Screen.AllScreens.Length; i++)
{
    if (Screen.AllScreens[i].Primary == true)
    {
        primaryMonitor = Screen.AllScreens[i].DeviceName;
    }
}

if (currentMonitor == primaryMonitor)
{
    Console.WriteLine($"Window is in primary monitor ({primaryMonitor})");
}
else
{
    Console.WriteLine($"Window is in ({currentMonitor}) and primary monitor is ({primaryMonitor})");
}

然而,获取主显示器可能有更简短的方法。


0

-1

您可以使用 Screen.FromControl 方法来获取当前窗体的屏幕,如下所示:

Screen screen = Screen.FromControl(this);

然后,您可以检查 Screen.Primary 来查看当前屏幕是否为主屏幕。


24
WPF 的 Window 不是 Windows Forms 的 Control,因此在这种情况下你不能使用 Screen.FromControl(this) - cprcrack
21
可以使用以下代码:Screen.FromHandle(new WindowInteropHelper(this).Handle); - David Rogers

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接