我在程序中正在执行以下操作:

Int32 currentMonitorCount = Screen.AllScreens.Length;

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

我的应用程序识别当前连接了多少台显示器,这一点非常重要。

但是,在几次插入/拔下显示器后,Screen.AllScreens.Length始终返回“2”。

我的显示器知道它没有连接(已进入“省电”模式),而控制面板知道它没有连接(它只显示了一个显示器)。

那我想念什么呢?如何确定只有一台显示器?

最佳答案

我查看了源代码(请记住我们可以使用MS Symbol服务器来完成此操作)。 AllScreens使用非托管API在第一次访问时获取屏幕,然后将结果存储在静态变量中以备后用。

这样做的结果是,如果程序运行时监视器的数目发生变化,则该数目将变为0。则Screen.AllScreens将不会接收更改。

解决此问题的最简单方法可能是直接调用unmanaged API
(或者您可能是邪恶的,并在询问之前使用反射将静态screens字段设置为null。请勿这样做。)

编辑:

如果您只需要知道计数,请在执行P/Invoke路由之前检查是否可以使用System.Windows.Forms.SystemInformation.MonitorCount(如注释中所建议)。这将直接调用GetSystemMetrics,并且可能已正确更新。

如果发现需要使用P/Invoke进行操作,下面是一个完整的示例,该示例演示了C#中非托管API的用法:

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;
    }
}

09-25 20:11