Screen.AllScreen没有给予正确的监视器数量监视器、数量、正确、Screen

2023-09-04 00:05:55 作者:余生没有北方

我做我的程序是这样的:

I am doing something like this in my program:

Int32 currentMonitorCount = Screen.AllScreens.Length;

if  (currentMonitorCount < 2)
{
   //Put app in single screen mode.
}
else
{
   //Put app in dual screen mode.
}

这是非常重要的我的应用程序识别多少监视器当前连接。

It is VERY important my application recognizes how many monitors are currently connected.

不过,我插上后/拔掉显示器几次,Screen.AllScreens.Length总是返回2。

However, after I plug/unplug the monitor a couple of times, Screen.AllScreens.Length always returns '2'.

我的显示器都知道它没有连接(它已经进入省电模式),以及控制面板都知道,它没有连接(只显示一台显示器)。

My monitor knows it's not connected (it has entered 'power save' mode), and the control panel knows that it's not connected (it shows only one monitor).

所以我缺少什么?怎样的 I 的弄清楚,这里只有一个显示器?

So what am I missing? How do I figure out that there's only one monitor?

推荐答案

我有一个看看源(记住我们可以做到使用MS符号服务器)。 AllScreens使用非托管API来获取屏幕上的第一的访问,然后将结果以供以后使用的静态变量。

I had a look at the source (remember we can do that using the MS Symbol servers). AllScreens uses an unmanaged API to get the screens on the first access, then stores the result in a static variable for later use.

这样做的结果是,如果显示器的改变的次数,同时程序运行;那么 Screen.AllScreens 不会拿起变化。

The consequence of this, is that if the number of monitors changes while your program is running; then Screen.AllScreens will not pick up the change.

要解决这个问题最简单的方法很可能会调用非托管API 直接。 (或者你可以是邪恶的,并使用反射来设置静态屏幕字段来询问之前空。不这样做)。

The easiest way to get around this would probably be to call the unmanaged API directly. (Or you could be evil, and use reflection to set the static screens field to null before asking. Don't do that).

如果你只需要知道计数,请检查您是否可以使用 System.Windows.Forms.SystemInformation.MonitorCount (如在评论中所建议的)才去为P / Invoke的路线。这就要求 GetSystemMetrics的直接,它可能是正确更新。

If you just need to know the count, check whether you can use System.Windows.Forms.SystemInformation.MonitorCount (as suggested in the comments) before going the P/Invoke route. This calls GetSystemMetrics directly, and it is probably correctly updated.

如果你发现你需要做的是使用P ​​/ Invoke,这里是一个完整的例子,演示了非托管的API从C#的用法:

If you find you need to do it using P/Invoke, here is a complete example that demonstrates the usage of the unmanaged API from C#:

using System;
using System.Runtime.InteropServices;

class Program
{
    public static void Main()
    {
        int monCount = 0;
        Rect r = new Rect();
        MonitorEnumProc callback = (IntPtr hDesktop, IntPtr hdc, ref Rect prect, int d) => ++monCount > 0;                                       
        if (EnumDisplayMonitors(IntPtr.Zero, IntPtr.Zero, callback, 0))
            Console.WriteLine("You have {0} monitors", monCount);
        else
            Console.WriteLine("An error occured while enumerating monitors");

    }
    [DllImport("user32")]
    private static extern bool EnumDisplayMonitors(IntPtr hdc, IntPtr lpRect, MonitorEnumProc callback, int dwData);

    private delegate bool MonitorEnumProc(IntPtr hDesktop, IntPtr hdc, ref Rect pRect, int dwData);

    [StructLayout(LayoutKind.Sequential)]
    private struct Rect
    {
        public int left;
        public int top;
        public int right;
        public int bottom;
    }
}