如何获取所有活动监视器的句柄

How to get handle of all active monitors

如何获取每台显示器的句柄?我需要知道每个物理监视器对应哪个监视器句柄。如果我也有每个显示器的位置和编号,我可以找到这个。但是我什至无法获得显示器的句柄。

我已经阅读了 EnumDisplayMonitors 的文档数十遍,但我尝试过的任何方法都不起作用。

我试过这样做:

oEnumDisplayMonitors := RegisterCallback("EnumMonitorsProc")
DllCall("EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", oEnumDisplayMonitors, "Ptr", 0)
omh := oEnumDisplayMonitors.monitorHandle
h := oEnumDisplayMonitors.hdc
olpr := oEnumDisplayMonitors.lpRect

EnumMonitorsProc(monitorHandle, hdc, lpRect, lParam){
}

但是 EnumMonitorsProc 的每个参数的值都是空的。

我也尝试了以下方法,按照 post 中的示例:https://www.autohotkey.com/boards/viewtopic.php?f=6&t=4606 但是,脚本一旦发出 DllCall("EnumDisplayMonitors",...

就会中止
Monitors := MDMF_Enum("")
    For HMON, M In Monitors {
        l := M.Left
        t := M.Top
        h := HMON
    }

MDMF_Enum(HMON := "") {
   Static EnumProc := RegisterCallback("MDMF_EnumProc")
   Static Monitors := {}
   If (HMON = "") ; new enumeration
      Monitors := {}
   If (Monitors.MaxIndex() = "") ; enumerate
    DllCall("EnumDisplayMonitors", "Ptr", 0, "Ptr", 0, "Ptr", EnumProc, "Ptr", &Monitors, "UInt")
   Return (HMON = "") ? Monitors : Monitors.HasKey(HMON) ? Monitors[HMON] : False
}

我需要所有监视器的句柄,而不仅仅是 active 监视器或 primary 监视器。

首先我们define the callback function that's going to be provided for the EnumDisplayMonitors函数。
Callback_Func := RegisterCallback("MONITORENUMPROC")
这也可以在不创建不必要的变量的情况下在线完成。

既然我们已经完成了,我们当然还需要创建我们所指的 MONITORENUMPROC 函数:

MONITORENUMPROC(hMonitor, hDC, pRECT, data)
{
   MsgBox, % hMonitor
   return true
}

我们只对句柄感兴趣,它是第一个参数。在这个小例子中我们可以忽略其他所有内容。
我们返回 true 以表明我们希望继续枚举其余的显示器,假设有任何显示器。这在回调函数的文档中指定。

好的,我们的回调函数就这样完成了,现在我们要调用 EnumDisplayMonitors 函数并将回调函数传递给它,这样它就可以发挥作用了。
DllCall("EnumDisplayMonitors", Ptr, 0, Ptr, 0, Ptr, Callback_Func, Ptr, 0)

我们将 null (pointer 0 in AHK) 传递给前两个参数,正如文档所建议的那样,如果您想要枚举所有可用的监视器。

对于第三个参数,我们传递回调函数的指针,它存储在我们的 Callback_Func 变量中。 (AHK 的 RegisterCallback 函数 returns 指向我们函数的指针)。

而对于第 4 个参数,我们只是再次传递 null,因为在这个小示例中我们不关心它。您可以通过那里传递 任何 数据,它会出现在我们用户定义的 MONITORENUMPROC 函数(我命名为 "data" 的函数的第 4 个参数中).
在您正在查看的库中,他们传递了一个指向他们自己的 "Monitors" 对象的指针。这只是他们使该功能具有双重用途的一种聪明方法。


基本上就是这样。我们为每个监视器的句柄打印一个消息框。
它如何工作的最小示例。假设您可能想知道哪个句柄是哪个监视器,您可以将句柄传递给另一个函数。
例如 GetMonitorInfo 函数,与您正在查看的那个库中的函数完全一样。

这是我为您制作的示例脚本:

Callback_Func := RegisterCallback("MONITORENUMPROC")
DllCall("EnumDisplayMonitors", Ptr, 0, Ptr, 0, Ptr, Callback_Func, Ptr, 0)

MONITORENUMPROC(hMonitor, hDC, pRECT, data)
{
   MsgBox, % hMonitor
   return true
}