4

我需要帮助将我从GetPhysicalMonitorsFromHMONITOR获得的 PHYSICAL_MONITOR 与显示器 DISPLAY_DEVICE.DeviceID 关联起来(例如“\?\DISPLAY#GSM59AB#5&932a802&1&UID261#{e6f07b5f-ee97-4a90- b076-33f57bf4eaa7 }”),它来自EnumDisplay_INTERACEF57bf4eaa7 }” ,或者以某种方式从 DISPLAY_DEVICE.DeviceID 获取 PHYSICAL_MONITOR,反之亦然。

我需要将它们都关联起来,因为:

  1. HANDLE PHYSICAL_MONITOR.hPhysicalMonitor 将用于低级监视器配置api,因为我需要向监视器发送命令。

  2. DISPLAY_DEVICE.DeviceID 用于使用 SetupAPI 从注册表中获取 EDID 结构(前 128 个字节对我来说就足够了,只需要制造商代码和型号)

1 和 2 已完成,问题是将 id 与物理监视器相关联。 也可以仅使用 SetupAPI 从注册表中获取所有监视器 EDID,但在这种情况下,无法获取物理监视器 HANDLE。

MSDN上的相同问题,未解决((

我还注意到一件事:此代码枚举所有监视器:

DWORD DispNum = 0;
DISPLAY_DEVICE DisplayDevice;
// Initialize DisplayDevice.
ZeroMemory(&DisplayDevice, sizeof(DisplayDevice));
DisplayDevice.cb = sizeof(DisplayDevice);

while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)))
{
    std::wstring deviceName = DisplayDevice.DeviceName;
    DISPLAY_DEVICE DisplayDeviceM;
    ZeroMemory(&DisplayDeviceM, sizeof(DisplayDeviceM));
    DisplayDeviceM.cb = sizeof(DisplayDeviceM);
    int monitorIndex = 0;
    while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &DisplayDeviceM, EDD_GET_DEVICE_INTERFACE_NAME))
    {
        std::wstring monitorID = DisplayDeviceM.DeviceID;
        ++monitorIndex;
    }
    DispNum++;
}

与此顺序相同:

BOOL CALLBACK EnumProc2(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData)
{
LPPHYSICAL_MONITOR pMons = NULL;
DWORD i, mcnt;

MONITORINFOEX mi;
ZeroMemory(&mi, sizeof(mi));
mi.cbSize = sizeof(mi);

GetMonitorInfo(hMonitor, &mi);

DISPLAY_DEVICE dd;
ZeroMemory(&dd, sizeof(dd));
dd.cb = sizeof(dd);
EnumDisplayDevices(mi.szDevice, 0, &dd, EDD_GET_DEVICE_INTERFACE_NAME);

monitorModelMnufac MdlManuf = findMonitorModelManufactFromEDID(dd.DeviceID);

if (!GetNumberOfPhysicalMonitorsFromHMONITOR(hMonitor, &mcnt)) return TRUE;
pMons = (LPPHYSICAL_MONITOR)malloc(mcnt * sizeof(PHYSICAL_MONITOR));
if (GetPhysicalMonitorsFromHMONITOR(hMonitor, mcnt, pMons))
    for (i = 0; i < mcnt; i++)
    {
        AddToMonHandles(pMons[i].hPhysicalMonitor, MdlManuf);
    }
free(pMons);
return TRUE;
}

物理监视器 HANDLE 是 0、1、2 等等,所以我可以从“monitorIndex”制作 HANDLE,但我不确定这样做是否安全。

我还在注册表中查找了物理监视器 HANDLE,但那里什么也没有。

还发现了对VideoPortDDCMonitorHelper很有帮助的功能,但正如我搜索的那样,它需要在驱动程序/过滤器中使用,并且不能从简单的可执行文件中使用。

还尝试反转 Windows dll,所有调用似乎都是从 WIN32U.dll 进行的,Ghidra 不想反编译它,或者我只是菜鸟。

请帮帮我:)

4

2 回答 2

0

我找到了一些有用的信息,希望对你有所帮助。

...
while ((EnumDisplayDevices(NULL, DispNum, &DisplayDevice, 0)))
    {
        std::wstring deviceName = DisplayDevice.DeviceName;
        DISPLAY_DEVICE DisplayDeviceM;
        ZeroMemory(&DisplayDeviceM, sizeof(DisplayDeviceM));
        DisplayDeviceM.cb = sizeof(DisplayDeviceM);
        int monitorIndex = 0;
        while (EnumDisplayDevices(deviceName.c_str(), monitorIndex, &DisplayDeviceM, EDD_GET_DEVICE_INTERFACE_NAME))
        {
            wcout << "deviceName:" << deviceName << endl;
            std::wstring monitorID = DisplayDeviceM.DeviceID;
            wcout <<"monitorID :"<< monitorID<< endl;
            ++monitorIndex;            
        }
        DispNum++;
    }
...

输出:

deviceName: \\.\DISPLAY1

然后使用EnumDisplayMonitors来获取HMONITOR并将其用作 的参数GetMonitorInfo

static BOOL CALLBACK MonitorEnum(HMONITOR hMon, HDC hdc, LPRECT lprcMonitor, LPARAM pData)
{
    cout << "hmonitor:" << hMon << endl;

    MONITORINFOEX mi;
    mi.cbSize = sizeof(mi);

    GetMonitorInfo(hMon, (LPMONITORINFO)&mi);

    wcout << "deviceName: "<<mi.szDevice << endl;

    DWORD cPhysicalMonitors;
    BOOL bSuccess = GetNumberOfPhysicalMonitorsFromHMONITOR(hMon, &cPhysicalMonitors);
    cout << "GetNumber: " << bSuccess << ", number of physical monitors: " << cPhysicalMonitors << endl;

    LPPHYSICAL_MONITOR pPhysicalMonitors = (LPPHYSICAL_MONITOR)malloc(cPhysicalMonitors * sizeof(PHYSICAL_MONITOR));
    bSuccess = GetPhysicalMonitorsFromHMONITOR(hMon, cPhysicalMonitors, pPhysicalMonitors);
    cout << "GetPhysicalMonitor: " << bSuccess << endl
        << "Handle: " << pPhysicalMonitors->hPhysicalMonitor << endl
        << "Description: ";
    wcout << (WCHAR*)(pPhysicalMonitors->szPhysicalMonitorDescription) << endl;;

    D(pPhysicalMonitors->hPhysicalMonitor);

    DestroyPhysicalMonitors(cPhysicalMonitors, pPhysicalMonitors);
    free(pPhysicalMonitors);

    cout << "---------------------------------------" << endl;

    return TRUE;
}

...

EnumDisplayMonitors(0, 0, MonitorEnum, NULL);

输出:

deviceName: \\.\DISPLAY1

如果两个输出相同,则它们对应同一个监视器。最后,我们可以将得到HMONITOR的作为 的参数GetPhysicalMonitorsFromHMONITOR,这样就可以得到hPhysicalMonitor我们需要的了。

于 2020-08-04T10:15:43.130 回答
0

我一直在寻找相似的目的之间EnumDisplayDevices的联系;GetPhysicalMonitorsFromHMONITOR我需要每个监视器的唯一 ID,以及设置 VCP 值的能力。

一些相关的帖子不让我相信有一个简单的答案。

我不确定它是否有任何帮助,但我发现ControlMyMonitor很有用。

跑步:

controlmymonitor.exe /smonitors

为每个监视器生成信息:

Monitor Device Name: "\\.\DISPLAY1\Monitor0"
Monitor Name: "VX4380 SERIES"
Serial Number: ""
Adapter Name: "NVIDIA GeForce GTX 760"
Monitor ID: "MONITOR\VSC5B34\{4d36e96e-e325-11ce-bfc1-08002be10318}\0004"

您可以轻松设置 VCP 值。例如,告诉显示器更改为 HDMI 1:

controlmymonitor.exe /SetValue "\\.\DISPLAY1\Monitor0" 60 17

此外,如果您调用EnumDisplayMonitors以获得PHYSICAL_MONITOR.hPhysicalMonitor,然后将该句柄传递给CapabilitiesRequestAndCapabilitiesReply,它会产生以下输出:

prot(monitor)
type(LCD)
model(VX4380)
cmds(01 02 03 07 0C E3 F3)
vcp(02 04 05 08 0B 0C 10 12 14(01 08 06 05 04 0B) 16 18 1A 52 60(0F 10 11 12) 62 87 8D(01 02) A5 AC AE B2 B6 C6 C8 CA CC(01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 12 14 16 17 1A 1E 24) D6(01 04 05) DC(00 01 02 03 05 08 1F) DF E0(00 01 02 03 14) EC(01 02 03) F6 F7(42 FF) FA(00 01 02) FB FC FD FE(00 01 02 04) FF)
mswhql(1)
asset_eep(40)
mccs_ver(2.2)

其中恰好包含型号。

希望上述命令产生的一些信息可以帮助您实现目标。

祝你好运!

于 2020-09-06T14:38:42.557 回答