c++ - 如何将 PHYSICAL_MONITOR 与监视器 DeviceID 关联

标签 c++ winapi multiple-monitors low-level low-level-api

我需要帮助的关联PHYSICAL_MONITOR这是我从GetPhysicalMonitorsFromHMONITOR获得与显示器DISPLAY_DEVICE.DeviceID(如 “\?\DISPLAY#GSM59AB#5 932a802&1&UID261#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}”),这是从EnumDisplayDevices,旗EDD_GET_DEVICE_INTERFACE_NAME使用,或以某种方式从 DISPLAY_DEVICE.DeviceID 获取 PHYSICAL_MONITOR,反之亦然。
我需要将它们都关联起来,因为:

  • HANDLE PHYSICAL_MONITOR.hPhysicalMonitor 将用于 lowlevelmonitorconfigurationapi,因为我需要向监视器发送命令。
  • DISPLAY_DEVICE.DeviceID 用于使用 SetupAPI 从注册表中获取 EDID 结构(前 128 个字节对我来说足够了,只需要制造商代码和型号)

  • 1 和 2 已完成,问题是将 id 与物理监视器相关联。
    Also it is possible to get 所有监视器仅使用 SetupAPI 从注册表中监控 EDID,但在这种情况下,不可能获得物理监视器 HANDLE。
    MSDN 上的 Same question,未解决((
    我还注意到一件事:
    此代码枚举所有监视器:
    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,但我不确定这样做是否安全。
    我还查看了注册表以找到物理监视器句柄,但没有。
    还找到了有用的函数 VideoPortDDCMonitorHelper,但正如我在谷歌上搜索的那样,它需要在驱动程序/过滤器中使用,并且不能从简单的可执行文件中使用。
    还尝试反转 Windows dll,所有调用似乎都是从 WIN32U.dll 发出的,而 Ghidra 不想反编译它,或者我只是个菜鸟。
    请帮帮我伙计们:)

    最佳答案

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

    ...
    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我们需要。

    关于c++ - 如何将 PHYSICAL_MONITOR 与监视器 DeviceID 关联,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63095216/

    相关文章:

    c++ - 覆盖常量表达式?

    c++ - 输入不传递到函数中

    c++ - 在c++中的区域语言设置下获取当前位置值

    java - 使用多个显示器时设置对话框位置

    java - C 和 C++ 中的 JNI 调用不同?

    c++ - 重置嵌入式 ruby​​ 解释器的状态

    c++ - 在 Win32 静态库中加载 XAML (WinRT/C++) 窗口

    c++ - HDC 内存泄漏

    Delphi 6 表单设置为使用 poDesktopCenter 定位自身,最终出现在 "extended"监视器上

    c# - 如何检查窗口在用户屏幕上是否完全可见?