我在我的程序中做这样的事情:
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).
那么我错过了什么?我如何确定只有一台显示器?
So what am I missing? How do I figure out that there's only one monitor?
我查看了源代码(请记住,我们可以使用 MS Symbol 服务器做到这一点).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 直接.(或者你可能是邪恶的,并在询问之前使用反射将静态 screens
字段设置为 null.不要那样做).
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).
如果您只需要知道计数,请在执行 P/Invoke 路由之前检查您是否可以使用 System.Windows.Forms.SystemInformation.MonitorCount
(如评论中所建议的那样).这会直接调用 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 来执行此操作,这里有一个完整示例,演示了 C# 中非托管 API 的用法:
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;
}
}
这篇关于Screen.AllScreen 没有给出正确的监视器计数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!