我有一个Windows应用程序,需要在运行时检测正确数量的已连接监视器。
到目前为止,我已经能够在Internet和Stack Overflow上找到的所有方法都失败了。无论是否实际连接屏幕,它们都返回1。并且当连接2个屏幕时,其中一些正确返回2,但是,当未连接任何屏幕时,没有一个返回0。当没有屏幕连接时,我需要它返回0。
即使检测屏幕是否已连接的方法也可以使用。
下面是我尝试过的6种方法的代码清单。
int numberOfScreens = 0;
numberOfScreens = Screen.AllScreens.Length; //1 DOESN'T WORK
numberOfScreens = SystemInformation.MonitorCount; //2 DOESN'T WORK
numberOfScreens = GetSystemMetrics(80); //3 DOESN'T WORK
/*4 DOESN'T WORK
* //This code was outside of the function
* [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;
* }
*/
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);
numberOfScreens = monCount;
} else {
Console.WriteLine("An error occured while enumerating monitors");
}
//5 DOESN'T WORK
ManagementObjectSearcher searcher =
new ManagementObjectSearcher("root\\CIMV2",
"SELECT * FROM Win32_PnPEntity where service =\"monitor\"");
numberOfScreens = searcher.Get().Count;
//6 DOESN'T WORK
var active = true;
var query = "select * from WmiMonitorBasicDisplayParams";
using (var wmiSearcher = new ManagementObjectSearcher("\\root\\wmi", query)) {
var results = wmiSearcher.Get();
foreach (ManagementObject wmiObj in results) {
// get the "Active" property and cast to a boolean, which should
// tell us if the display is active. I've interpreted this to mean "on"
active = (Boolean)wmiObj["Active"];
}
}
Console.WriteLine(active);
如果还有其他可靠的方法来检测正确的显示器数量,我将不胜感激。
谢谢!
另一方面,在Default_Monitor注册表中设置了EDID_OVERRIDE,因此无论发生什么情况,EDID都不会改变。这不是我可以改变的东西。但这可能是Windows表示实际上没有显示器的原因。这将意味着它不会根据实际连接的显示器数来计算,而是根据它认为要渲染的显示器数来计算。
鉴于这种怀疑,有没有一种方法可以检测实际连接的显示器数量?例如,插入了多少条HDMI / DVI / VGA电缆,而不是Windows认为要渲染到的屏幕数?
答案 0 :(得分:0)
经过大量的修补和头部刮擦,我设法创建了一个可靠地返回正确数量的已连接屏幕的函数,即使该数量在程序运行时发生了变化,即使已连接屏幕的数量为0
这意味着它也可以用于检测屏幕/显示器/监视器是否已完全连接到计算机。
using System;
using System.Management;
/// <summary>
/// Returns the number of monitors currently connected to the computer.
/// </summary>
/// <returns>(int) number of monitors</returns>
public int getNumberOfConnectedMonitors() {
int numberOfMonitors = 1;
//Detect number of monitors. However, this does NOT work when no monitors are connected. It instead gives a 1.
ManagementObjectSearcher searcher = new ManagementObjectSearcher("root\\CIMV2", "SELECT * FROM Win32_PnPEntity where service =\"monitor\"");
numberOfMonitors = searcher.Get().Count;
//Get's the monitor's instance name. "Default_Monitor" is the "monitor" Windows defaults to when nothing is connected
string activeScreen = "";
using (var wmiSearcher = new ManagementObjectSearcher("\\root\\wmi", "select * from WmiMonitorBasicDisplayParams")) {
var results = wmiSearcher.Get();
foreach (ManagementObject wmiObj in results) {
// tell us if the display is active
var active = (Boolean)wmiObj["Active"];
//Get the instance name of the active monitor
if (active) {
activeScreen = (string)wmiObj["InstanceName"];
}
}
}
//If Windows says only one monitor is connected and that monitor is Default_Monitor, then that means that there are no monitors detected by Windows
if(numberOfMonitors == 1 && activeScreen.Contains("Default_Monitor")) {
numberOfMonitors = 0;
}
return numberOfMonitors;
}
上面的函数是方法5和方法6的科学怪人混合体(在问题中可见)。
首先,它从方法5获取监视器的数量,当连接的监视器的数量大于0时(至少对于我测试的监视器而言),该方法可靠地给出了正确的数量。但是,当实际上有0个监视器连接时,它将返回1。
其次,它通过方法6的修改版本获得活动监视器之一的名称。方法6使用WmiMonitorBasicDisplayParams class获取有关已连接监视器的信息。首先,它检查监视器是否处于活动状态。如果是,则它将获取监视器的实例名称。实例名称的格式类似于DISPLAY\(monitorNameHere)\(seeminglyRandomValuesHere)
。
如果仅连接了一个监视器,并且该监视器的实例名称包含“ Default_Monitor”,则表示当前未连接任何有效的监视器,并且该函数返回0。
“ Default_Monitor”是Windows赋予未检测到监视器的“监视器”的名称。 (至少没有提供有效EDID的监视器)
现在,可能只是原始功能无法使用的原因是因为我将Default_Monitor设置为拥有自己的EDID。但是,无论如何,我认为此功能仍然可靠。
此功能对于检测是否已连接屏幕/显示器/显示器也非常有用(因为如果没有,则返回0),这也是我在互联网上其他任何地方都找不到的东西。相信即使我没有为Default_Monitor设置EDID,这些函数也不会返回0。
无论哪种方式,此功能都可以在我的测试中可靠地工作。