是否有可能从Windows对象管理器路径获得HMONITOR句柄?



我有一个像这样的路径:

\?DISPLAY#IVM1A3E#5&1778d8b3&1&UID260#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}

我想要一个HMONITOR手柄。

使用WinObj我可以看到在全局??这是一个指向Device<number>的符号链接

我该怎么做呢?

编辑:

路径可以分成三部分。首先是\?前缀,然后是第二个DISPLAY#IVM1A3E#5&1778d8b3&1&UID260,如果#取代,它与设备实例ID相同。第三,{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}是Monitor设备的GUID。

有了设备实例ID,我可以使用CM_Get_ChildCM_Get_Sibling遍历设备树,使用CM_Get_Device_ID检查设备名称。但这只给了我一个DEVINST,而不是HMONITOR

您可以使用连接和配置显示(CCD) API,特别是QueryDisplayConfig函数,它可以检索当前设置中所有显示设备或视图的所有可能显示路径的信息。

使用以下代码,您将获得设备路径和监视器(及其句柄)之间的对应关系。
#include <Windows.h>
#include <stdio.h>
#include <vector>
#include <tuple>
#include <string>
int main()
{
// get all paths
UINT pathCount;
UINT modeCount;
if (GetDisplayConfigBufferSizes(QDC_ONLY_ACTIVE_PATHS, &pathCount, &modeCount))
return 0;
std::vector<DISPLAYCONFIG_PATH_INFO> paths(pathCount);
std::vector<DISPLAYCONFIG_MODE_INFO> modes(modeCount);
if (QueryDisplayConfig(QDC_ONLY_ACTIVE_PATHS, &pathCount, paths.data(), &modeCount, modes.data(), nullptr))
return 0;
// enum all monitors => (handle, device name)>
std::vector<std::tuple<HMONITOR, std::wstring>> monitors;
EnumDisplayMonitors(nullptr, nullptr, [](HMONITOR hmon, HDC hdc, LPRECT rc, LPARAM lp)
{
MONITORINFOEX mi = {};
mi.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(hmon, &mi);
auto monitors = (std::vector<std::tuple<HMONITOR, std::wstring>>*)lp;
monitors->push_back({ hmon, mi.szDevice });
return TRUE;
}, (LPARAM)&monitors);
// for each path, get GDI device name and compare with monitor device name
for (UINT i = 0; i < pathCount; i++)
{
DISPLAYCONFIG_TARGET_DEVICE_NAME deviceName = {};
deviceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_TARGET_NAME;
deviceName.header.size = sizeof(DISPLAYCONFIG_TARGET_DEVICE_NAME);
deviceName.header.adapterId = paths[i].targetInfo.adapterId;
deviceName.header.id = paths[i].targetInfo.id;
if (DisplayConfigGetDeviceInfo((DISPLAYCONFIG_DEVICE_INFO_HEADER*)&deviceName))
continue;
wprintf(L"Monitor Friendly Name : %sn", deviceName.monitorFriendlyDeviceName);
wprintf(L"Monitor Device Path   : %sn", deviceName.monitorDevicePath);
DISPLAYCONFIG_SOURCE_DEVICE_NAME sourceName = {};
sourceName.header.type = DISPLAYCONFIG_DEVICE_INFO_GET_SOURCE_NAME;
sourceName.header.size = sizeof(DISPLAYCONFIG_SOURCE_DEVICE_NAME);
sourceName.header.adapterId = paths[i].targetInfo.adapterId;
sourceName.header.id = paths[i].sourceInfo.id;
if (DisplayConfigGetDeviceInfo((DISPLAYCONFIG_DEVICE_INFO_HEADER*)&sourceName))
continue;
wprintf(L"GDI Device Name       : %sn", sourceName.viewGdiDeviceName);
// find the monitor with this device name
auto mon = std::find_if(monitors.begin(), monitors.end(), [&sourceName](std::tuple<HMONITOR, std::wstring> t)
{
return !std::get<1>(t).compare(sourceName.viewGdiDeviceName);
});
wprintf(L"Monitor Handle        : %pn", std::get<0>(*mon));
wprintf(L"n");
}
return 0;
}

在我的PC上(有两个显示器),它将输出如下内容:

Monitor Friendly Name : C27HG7x
Monitor Device Path   : \?DISPLAY#SAM0E16#7&307b5912&0&UID1024#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
GDI Device Name       : \.DISPLAY2
Monitor Handle        : 0000000000160045
Monitor Friendly Name : DELL U2715H
Monitor Device Path   : \?DISPLAY#DELD069#7&307b5912&0&UID1028#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
GDI Device Name       : \.DISPLAY1
Monitor Handle        : 0000000000020083

注意,你也可以使用WinRT的DisplayManager class =>DisplayView class =>路径属性,DisplayPath类,=>目标属性=>TryGetMonitor函数

最新更新