windows - 如何从显示设备名称中获取 HMONITOR 句柄?

标签 windows winapi multiple-monitors

我想获得一个监视器句柄 (HMONITOR),它可以与 Windows 多监视器 API 一起用于连接到系统的特定监视器 索引。例如,假设我有三个显示器连接到我的系统并构成我桌面的一部分;我想得到一个句柄来监视 3。

我已经知道如何通过调用 EnumDisplayDevices 函数按索引获取特定监视器的设备名称。例如:

HMONITOR MonitorFromIndex(int index /* (zero-indexed) */)
{
    DISPLAY_DEVICE dd;
    dd.cb = sizeof(dd);
    if (EnumDisplayDevices(NULL, index, &dd, 0) != FALSE)
    {
       // We found a match; make sure that it's part of the desktop.
       if ((dd.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) == DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)
       {
          // Yup. Now we've got the name of the device:
          std::cout << dd.DeviceName << std::endl;

          // But how do I obtain an HMONITOR for this device?
          // ...
       }
    }
   return NULL;  // indicate failure
}

在上面的代码中,我们找到了所需设备的名称 (dd.DeviceName)。我可以通过调用 CreateDC 使用此名称为该监视器创建 DC:

HDC hDC = CreateDC(dd.DeviceName, dd.DeviceName, NULL, NULL);

我可以通过调用 EnumDisplaySettings 获取有关该监视器的信息:

DEVMODE dm;
dm.dmSize        = sizeof(dm);
dm.dmDriverExtra = 0;
if (EnumDisplaySettings(dd.DeviceName, ENUM_CURRENT_SETTINGS, &dm) != FALSE)
{
    std::cout << "The monitor supports " << dm.dmBitsPerPel << " bits per pixel." << std::endl;
}

这一切都很好,但我想要那个显示器的句柄。我怎样才能得到它?

我尝试调用 EnumDisplayMonitors,将句柄传递到我使用 CreateDC 创建的设备上下文,希望获得传递给回调函数的监视器的句柄,但没有这样的运气。从未调用回调函数,EnumDisplayMonitors 返回 FALSE(未设置错误代码):

struct FoundMatch
{
   BOOL     found;
   HMONITOR hMonitor;
};

BOOL CALLBACK MonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, LPARAM dwData)
{
   FoundMatch* pfm = reinterpret_cast<FoundMatch*>(dwData);
   pfm->found    = TRUE;
   pfm->hMonitor = hMonitor;
   return FALSE;  // stop enumerating
}

// elsewhere, after getting the device name and using it to create a DC
FoundMatch fm;
fm.found    = FALSE;
fm.hMonitor = NULL;
BOOL result = EnumDisplayMonitors(hDC, NULL, MonitorEnumProc, reinterpret_cast<LPARAM>(&fm));

最佳答案

很抱歉这么晚回复,但也许有人会觉得这有用。

多显示器 API 至少可以说是极简主义的。获得 dd.DeviceName 后,您似乎必须通过 EnumDisplayMonitors() 枚举,直到找到 dd.DeviceName 的匹配项> 针对 MONITORINFOEX.szDevice

MONITORINFOEX结构可以通过调用GetMonitorInfo()获取。

这是一个不可编译的 C++11 伪代码:

struct DataBag
{
    HMONITOR hmon;
    TCHAR* devname;
} bag;

bag.hmon = NULL;
bag.devname = &dd.DeviceName;

BOOL bRes = EnumDisplayMonitors(
    NULL, NULL,
    [](HMONITOR hMonitor, HDC hDC, LPRECT rc, LPARAM data) -> BOOL {
        auto& bag = *reinterpret_cast<DataBag*>(data);
        MONITORINFOEX mi;
        mi.cbSize = sizeof(mi);
        if (/* match bag.devname against mi.szDevice */ && GetMonitorInfo(hMonitor, &mi))
        {
            bag.hmon = hMonitor;
            return FALSE;
        }
        return TRUE;
    },
    reinterpret_cast<LPARAM>(&bag));
if (bRes && bag.hmon)
{
    // Monitor found!
}

关于windows - 如何从显示设备名称中获取 HMONITOR 句柄?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34987695/

相关文章:

您可以使用除以零来检测附加到您的进程的调试器吗

windows - 如何启用 'Microsoft.Windows.Common-Controls'进行特定控制?

multiple-monitors - 有没有办法将宽屏显示器分成两个或多个虚拟显示器?

C++ 代码转储 "random"数据

windows - 如何检测文件夹是否为空(Windows 批处理文件)?

c++ - 计算从客户端发送到服务器的数据包数量?

c++ - win32(全屏)无边框窗口重叠任务栏

c++ - MFC中如何获取可见显示器的宽度?

c# - Process.Start 和双监视器

windows - 如何为多个命令定义 DOSKEY 别名?