C++ 在Windows 7/8/10 Win32 C+中检测/识别监视器连接到的端口(HDMI,其他)+;
我能够检测连接到我的系统的所有监视器。通过使用以下Windows API调用,我可以获得很多关于它们的相关信息: 我正在开发的系统是一个AIO(一体机),带有两个监视器。它有一个外部HDMI输出,我可以连接和外部显示器。然后,通过端口复制器,我可以连接第四个监视器。所有的显示器都在扩展我的桌面,而且工作正常 我的任务是检测通过HDMI端口连接的监视器。我可以使用上述API提取的监视器信息不提供任何特定信息,通过这些信息我可以检测端口类型(例如HDMI或USB) 有人知道使用什么API吗?谢谢 您可以使用该方法获取监视器的C++ 在Windows 7/8/10 Win32 C+中检测/识别监视器连接到的端口(HDMI,其他)+;,c++,windows,winapi,windows-8.1,wmi,C++,Windows,Winapi,Windows 8.1,Wmi,我能够检测连接到我的系统的所有监视器。通过使用以下Windows API调用,我可以获得很多关于它们的相关信息: 我正在开发的系统是一个AIO(一体机),带有两个监视器。它有一个外部HDMI输出,我可以连接和外部显示器。然后,通过端口复制器,我可以连接第四个监视器。所有的显示器都在扩展我的桌面,而且工作正常 我的任务是检测通过HDMI端口连接的监视器。我可以使用上述API提取的监视器信息不提供任何特定信息,通过这些信息我可以检测端口类型(例如HDMI或USB) 有人知道使用什么API吗?谢
设备ID
,然后获取WMI类(从Windows Vista开始提供)和返回枚举的VideoOutputTechnology
属性
请尝试下一个示例代码
#include "stdafx.h"
#include <atlstr.h>
#define _WIN32_DCOM
#include <iostream>
using namespace std;
#include <comdef.h>
#include <Wbemidl.h>
# pragma comment(lib, "wbemuuid.lib")
typedef enum _D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY {
D3DKMDT_VOT_UNINITIALIZED = -2,
D3DKMDT_VOT_OTHER = -1,
D3DKMDT_VOT_HD15 = 0,
D3DKMDT_VOT_SVIDEO = 1,
D3DKMDT_VOT_COMPOSITE_VIDEO = 2,
D3DKMDT_VOT_COMPONENT_VIDEO = 3,
D3DKMDT_VOT_DVI = 4,
D3DKMDT_VOT_HDMI = 5,
D3DKMDT_VOT_LVDS = 6,
D3DKMDT_VOT_D_JPN = 8,
D3DKMDT_VOT_SDI = 9,
D3DKMDT_VOT_DISPLAYPORT_EXTERNAL = 10,
D3DKMDT_VOT_DISPLAYPORT_EMBEDDED = 11,
D3DKMDT_VOT_UDI_EXTERNAL = 12,
D3DKMDT_VOT_UDI_EMBEDDED = 13,
D3DKMDT_VOT_SDTVDONGLE = 14,
#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WDDM1_3_M1)
D3DKMDT_VOT_MIRACAST = 15,
#endif
D3DKMDT_VOT_INTERNAL = 0x80000000,
D3DKMDT_VOT_SVIDEO_4PIN = D3DKMDT_VOT_SVIDEO,
D3DKMDT_VOT_SVIDEO_7PIN = D3DKMDT_VOT_SVIDEO,
D3DKMDT_VOT_RF = D3DKMDT_VOT_COMPOSITE_VIDEO,
D3DKMDT_VOT_RCA_3COMPONENT = D3DKMDT_VOT_COMPONENT_VIDEO,
D3DKMDT_VOT_BNC = D3DKMDT_VOT_COMPONENT_VIDEO
} D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY;
_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY GetConnectorInfo(LPCWSTR ShortDeviceID)
{
_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY result = D3DKMDT_VOT_OTHER;
BSTR strNetworkResource;
strNetworkResource = L"\\\\.\\root\\WMI";
HRESULT hres;
hres = CoInitializeEx(0, COINIT_MULTITHREADED);
if (FAILED(hres))
{
cout << "Failed to initialize COM library. Error code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
hres = CoInitializeSecurity(
NULL,
-1, // COM authentication
NULL, // Authentication services
NULL, // Reserved
RPC_C_AUTHN_LEVEL_DEFAULT, // Default authentication
RPC_C_IMP_LEVEL_IMPERSONATE, // Default Impersonation
NULL, // Authentication info
EOAC_NONE, // Additional capabilities
NULL // Reserved
);
if (FAILED(hres))
{
cout << "Failed to initialize security. Error code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
CoUninitialize();
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
IWbemLocator *pLoc = NULL;
hres = CoCreateInstance(CLSID_WbemLocator, 0, CLSCTX_INPROC_SERVER, IID_IWbemLocator, (LPVOID *)&pLoc);
if (FAILED(hres))
{
cout << "Failed to create IWbemLocator object." << " Err code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
CoUninitialize();
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
IWbemServices *pSvc = NULL;
hres = pLoc->ConnectServer(
_bstr_t(strNetworkResource), // Object path of WMI namespace
NULL, // User name. NULL = current user
NULL, // User password. NULL = current
0, // Locale. NULL indicates current
NULL, // Security flags.
0, // Authority (e.g. Kerberos)
0, // Context object
&pSvc // pointer to IWbemServices proxy
);
if (FAILED(hres))
{
cout << "Could not connect. Error code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
pLoc->Release();
CoUninitialize();
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
hres = CoSetProxyBlanket(
pSvc, // Indicates the proxy to set
RPC_C_AUTHN_WINNT, // RPC_C_AUTHN_xxx
RPC_C_AUTHZ_NONE, // RPC_C_AUTHZ_xxx
NULL, // Server principal name
RPC_C_AUTHN_LEVEL_CALL, // RPC_C_AUTHN_LEVEL_xxx
RPC_C_IMP_LEVEL_IMPERSONATE, // RPC_C_IMP_LEVEL_xxx
NULL, // client identity
EOAC_NONE // proxy capabilities
);
if (FAILED(hres))
{
cout << "Could not set proxy blanket. Error code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
IEnumWbemClassObject* pEnumerator = NULL;
hres = pSvc->ExecQuery(L"WQL", L"SELECT InstanceName, VideoOutputTechnology FROM WmiMonitorConnectionParams",
WBEM_FLAG_FORWARD_ONLY | WBEM_FLAG_RETURN_IMMEDIATELY, NULL, &pEnumerator);
if (FAILED(hres))
{
cout << "ExecQuery failed" << " Error code = 0x" << hex << hres << endl;
cout << _com_error(hres).ErrorMessage() << endl;
pSvc->Release();
pLoc->Release();
CoUninitialize();
cout << "press enter to exit" << endl;
cin.get();
std::exit(1);
}
IWbemClassObject *pclsObj = NULL;
ULONG uReturn = 0;
BOOL bFound = false;
while (pEnumerator)
{
HRESULT hr = pEnumerator->Next(WBEM_INFINITE, 1, &pclsObj, &uReturn);
if (0 == uReturn || FAILED(hr))
break;
VARIANT vtProp;
CString DeviceID;
hr = pclsObj->Get(L"InstanceName", 0, &vtProp, 0, 0);// String
if (!FAILED(hr))
{
if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
{ }
else
{
DeviceID.Format(L"%s", vtProp.bstrVal);
DeviceID = DeviceID.Mid(8, DeviceID.Find(L"\\", 9) - 8);
bFound = DeviceID.Compare(ShortDeviceID) == 0;
}
}
VariantClear(&vtProp);
if (bFound)
{
hr = pclsObj->Get(L"VideoOutputTechnology", 0, &vtProp, 0, 0);// Uint32
if (!FAILED(hr))
{
if ((vtProp.vt == VT_NULL) || (vtProp.vt == VT_EMPTY))
result = D3DKMDT_VOT_OTHER;
else
{
result = (_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY)vtProp.uintVal;
}
}
}
VariantClear(&vtProp);
pclsObj->Release();
pclsObj = NULL;
if (bFound)
break;
}
pSvc->Release();
pLoc->Release();
pEnumerator->Release();
if (pclsObj != NULL)
pclsObj->Release();
CoUninitialize();
return result;
}
void GetDisplayInfo()
{
DISPLAY_DEVICE lpDisplayDevice;
lpDisplayDevice.cb = sizeof(lpDisplayDevice);
DWORD iDevNum = 0;
CString DeviceID;
while (EnumDisplayDevices(0, iDevNum, &lpDisplayDevice, 0))
{
DISPLAY_DEVICE lpDisplayDevice2;
ZeroMemory(&lpDisplayDevice2, sizeof(lpDisplayDevice2));
lpDisplayDevice2.cb = sizeof(lpDisplayDevice2);
DWORD devMon = 0;
while (EnumDisplayDevices(lpDisplayDevice.DeviceName, devMon, &lpDisplayDevice2, 0))
{
if (lpDisplayDevice2.StateFlags & DISPLAY_DEVICE_ACTIVE && !(lpDisplayDevice2.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER))
{
DeviceID.Format(L"%s", lpDisplayDevice2.DeviceID);
wcout << DeviceID.GetString() << endl;
DeviceID = DeviceID.Mid(8, DeviceID.Find(L"\\", 9) - 8);
_D3DKMDT_VIDEO_OUTPUT_TECHNOLOGY VideoOutputTechnology = GetConnectorInfo(DeviceID.GetString());
switch (VideoOutputTechnology)
{
case D3DKMDT_VOT_HDMI:
wcout << " VideoOutputTechnology : HDMI" << endl;
break;
case D3DKMDT_VOT_INTERNAL:
wcout << " VideoOutputTechnology : Internal Monitor" << endl;
break;
default:
wcout << " VideoOutputTechnology : " << VideoOutputTechnology << endl;
break;
}
}
devMon++;
ZeroMemory(&lpDisplayDevice2, sizeof(lpDisplayDevice2));
lpDisplayDevice2.cb = sizeof(lpDisplayDevice2);
}
ZeroMemory(&lpDisplayDevice, sizeof(lpDisplayDevice));
lpDisplayDevice.cb = sizeof(lpDisplayDevice);
iDevNum++;
}
}
int main(int argc, char* argv[])
{
GetDisplayInfo();
cout << "press enter to exit" << endl;
cin.get();
return 0;
}
很多显示器都支持DDC/CI 2B,如果显示器支持VCP功能
60h-输入源,则很容易询问显示器本身连接到了什么
并非所有显示器都支持该协议,尤其是大多数集成平板和非常旧的CRT,也不能保证任何特定的显示器都支持该VCP功能
char* INPUT_SOURCES[] = {
"Unknown",
"Analog video (R/G/B) 1",
"Analog video (R/G/B) 2",
"Digital video (TMDS) 1 DVI",
"Digital video (TMDS) 2 DVI",
"Composite video 1",
"Composite video 2",
"S-video 1",
"S-video 2",
"Tuner 1",
"Tuner 2",
"Tuner 3",
"Component video (YPbPr/ YCbCr) 1",
"Component video (YPbPr/ YCbCr) 2",
"Component video (YPbPr/ YCbCr) 3",
"DisplayPort 1",
"DisplayPort 2",
"Digital Video (TMDS) 3 HDMI",
"Digital Video (TMDS) 4 HDMI"
};
char* getInputSourceName(DWORD value)
{
if (value > ARRAYSIZE(INPUT_SOURCES)) value = 0;
return INPUT_SOURCES[value];
}
BOOL CALLBACK enumNextMonitor(HMONITOR monitor, HDC dc, LPRECT dRect, LPARAM param)
{
DWORD physNum;
if (GetNumberOfPhysicalMonitorsFromHMONITOR(monitor, &physNum)) {
if (physNum == 0) return 1;
PHYSICAL_MONITOR* displays = malloc(physNum * sizeof(PHYSICAL_MONITOR));
if (GetPhysicalMonitorsFromHMONITOR(monitor, physNum, displays)) {
for (DWORD i = 0; i < physNum; i++) {
DWORD value;
if (GetVCPFeatureAndVCPFeatureReply(displays[i].hPhysicalMonitor, 0x60, NULL, &value, NULL)) {
printf(
"Display: %s, input is %s\n",
displays[i].szPhysicalMonitorDescription,
getInputSourceName(value)
);
} else {
printf(
"Display: %s, unknown input type\n",
displays[i].szPhysicalMonitorDescription
);
}
}
}
free(displays);
}
}
int main()
{
EnumDisplayMonitors(NULL, NULL, enumNextMonitor, NULL);
}
char*输入_源[]={
“未知”,
“模拟视频(R/G/B)1”,
“模拟视频(R/G/B)2”,
“数字视频(TMDS)1 DVI”,
“数字视频(TMDS)2 DVI”,
“合成视频1”,
“合成视频2”,
“S-video 1”,
“S-video 2”,
“调谐器1”,
“调谐器2”,
“调谐器3”,
“分量视频(YPbPr/YCbCr)1”,
“分量视频(YPbPr/YCbCr)2”,
“分量视频(YPbPr/YCbCr)3”,
“显示端口1”,
“显示端口2”,
“数字视频(TMDS)3 HDMI”,
“数字视频(TMDS)4 HDMI”
};
char*getInputSourceName(DWORD值)
{
如果(值>阵列化(输入源))值=0;
返回输入_源[值];
}
布尔回调枚举下一个监视器(HMONITOR监视器、HDC dc、LPRECT dRect、LPARAM参数)
{
德沃德·菲斯南;
if(从HMonitor(监视器和物理监视器)获取物理监视器的编号){
如果(physNum==0)返回1;
物理监视器*显示=malloc(物理监视器的大小);
if(从HMonitor(监视器、物理监视器、显示器)获取物理监视器){
for(DWORD i=0;i
作为备用方案,monitor EDID通常包含有关所用连接类型的有限信息–它可能像“模拟”或“数字”一样简单,具有更详细的数字连接细分,用于更精细的实现
可用于获取显示EDID的SetupAPI还提供了其连接的显示适配器的参考。也许还可以查询连接详细信息。@RRUZ,谢谢您的示例代码。您知道如何使用多个同名监视器(如SNY7702)工作吗?
char* INPUT_SOURCES[] = {
"Unknown",
"Analog video (R/G/B) 1",
"Analog video (R/G/B) 2",
"Digital video (TMDS) 1 DVI",
"Digital video (TMDS) 2 DVI",
"Composite video 1",
"Composite video 2",
"S-video 1",
"S-video 2",
"Tuner 1",
"Tuner 2",
"Tuner 3",
"Component video (YPbPr/ YCbCr) 1",
"Component video (YPbPr/ YCbCr) 2",
"Component video (YPbPr/ YCbCr) 3",
"DisplayPort 1",
"DisplayPort 2",
"Digital Video (TMDS) 3 HDMI",
"Digital Video (TMDS) 4 HDMI"
};
char* getInputSourceName(DWORD value)
{
if (value > ARRAYSIZE(INPUT_SOURCES)) value = 0;
return INPUT_SOURCES[value];
}
BOOL CALLBACK enumNextMonitor(HMONITOR monitor, HDC dc, LPRECT dRect, LPARAM param)
{
DWORD physNum;
if (GetNumberOfPhysicalMonitorsFromHMONITOR(monitor, &physNum)) {
if (physNum == 0) return 1;
PHYSICAL_MONITOR* displays = malloc(physNum * sizeof(PHYSICAL_MONITOR));
if (GetPhysicalMonitorsFromHMONITOR(monitor, physNum, displays)) {
for (DWORD i = 0; i < physNum; i++) {
DWORD value;
if (GetVCPFeatureAndVCPFeatureReply(displays[i].hPhysicalMonitor, 0x60, NULL, &value, NULL)) {
printf(
"Display: %s, input is %s\n",
displays[i].szPhysicalMonitorDescription,
getInputSourceName(value)
);
} else {
printf(
"Display: %s, unknown input type\n",
displays[i].szPhysicalMonitorDescription
);
}
}
}
free(displays);
}
}
int main()
{
EnumDisplayMonitors(NULL, NULL, enumNextMonitor, NULL);
}