我在程序中正在执行以下操作:
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;
}
}