在Windows系统中,有没有一种方法可以检测显示器的状态(开启或关闭)?

24

有没有人知道在Windows(XP/Vista/2000/2003)中获取当前显示器状态(开启或关闭)的API?

我的所有搜索似乎都表明没有真正的方法来做到这一点。

这个线程 尝试使用 GetDevicePowerState,但根据微软文档,它不能用于显示设备。

在Vista中,我可以监听 GUID_MONITOR_POWER_ON 但当手动关闭监视器时,看起来我并没有收到事件。

在XP中,我可以钩取 WM_SYSCOMMAND SC_MONITORPOWER,寻找状态2。 这仅适用于系统触发的关闭情况。

WMI Win32_DesktopMonitor类似乎也无助于解决这个问题。

编辑:这里是关于comp.os.ms-windows.programmer.win32的 讨论,表明没有可靠的方法来做到这一点。

还有其他人有什么其他想法吗?


相关问题:http://stackoverflow.com/questions/328490/monitoring-a-displays-state-in-python - CesarB
1
您想通过这些信息达到什么目的呢?也许我们可以帮助解决实际问题。祝好。 - Mick
1
大致估算与计算机物理连接的显示器消耗的功率。 - Sam Saffron
9个回答

16

GetDevicePowerState有时对于监视器有效。如果存在,则可以打开\\.\LCD设备。在使用完毕后立即关闭它。

基本上,你没什么办法—除了编写设备驱动程序并过滤所有显示驱动程序链上传递的电源IRP之外,没有可靠的方法来检测监视器的电源状态。而且这也不是非常可靠的。


1
我认为这是最接近问题答案的回答。硬件制造商没有在DVI标准中提供那种通信水平,这是真正的失败。 - Sam Saffron
1
严肃地说,在你完成后立即关闭它。我曾经因为没有这样做而在迈克尔·戴尔的笔记本电脑上破坏了演示模式 :) - Roger Lipscombe
GetDevicePowerState 的文档说明:“此函数无法用于查询显示设备的电源状态。” - skst
除非在Windows Vista和现在之间更改了某些内容(这是可能的),否则文档是错误的。该函数不能用于可靠地查询显示设备的电源状态,但它在我们尝试过的大多数(几千台)计算机上确实有效。 - Roger Lipscombe

13

您可以连接网络摄像头,将其对准屏幕,并对接收到的图像进行分析 ;)


6
但是您可能会将反射视为屏幕动作。我认为您正在将设备驱动程序问题转化为图像处理问题。我喜欢这个想法 :) - cpatrick
3
这项技术被用来监控偏远地区装备齐全的机架。将摄像头对准机架,观察指示灯中是否有“异常”的变化。这种方法虽然有些笨拙,但在某些情况下它是唯一合理的答案。 - RBerteig

7
在基于显示器状态进行任何操作之前,请记住用户可以使用具有远程桌面的其他系统的计算机,这些计算机不需要连接显示器 - 因此不要基于显示器状态关闭任何可视化。

2
Windows API允许您确定显示器是否是“真实的”。请参见:DISPLAY_DEVICE_MIRRORING_DRIVER。 - Sam Saffron
远程桌面应用程序仍会影响屏幕保护程序,不是吗?(至少RealVNC是这样的。)我知道Windows自己的远程桌面会话使用另一个系统,所以那里可能会有所不同。 - Macke

7

你不能这样做。

看起来所有监视器电源功能都连接到"电源安全模式"
在搜索后,我发现这里有连接SC_MONITORPOWER消息和系统值的代码(第二个帖子)
我使用该代码测试系统值是否会在我手动关闭监视器时发生更改。

int main()
{
    for(;monitorOff()!=1;)
        Sleep(500);
    return 0;
}//main

即使我关闭了显示器,代码也不会停止运行。
下面是monitorOff函数的代码:

int monitorOff()
{
    const GUID MonitorClassGuid =
        {0x4d36e96e, 0xe325, 0x11ce, 
            {0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}};

    list<DevData> monitors;
    ListDeviceClassData(&MonitorClassGuid, monitors);

    list<DevData>::iterator it = monitors.begin(),
                            it_end = monitors.end();
    for (; it != it_end; ++it)
    {
        const char *off_msg = "";

        //it->PowerData.PD_PowerStateMapping
        if (it->PowerData.PD_MostRecentPowerState != PowerDeviceD0)
        {
            return 1;
        }
    }//for

    return 0;
}//monitorOff

结论:当您手动关闭显示器时,您无法通过Windows捕获它(如果没有不寻常的驱动程序界面),因为所有Windows功能都连接到"电源安全模式"


2

这个接口有没有使用示例? - c00000fd
有一个,但它只支持Windows XP,它是DirectX SDK的一部分。 - Fraser
@Fraser 你确定吗?我似乎在2010年6月的SDK中找不到它:https://i.imgur.com/NPK0jjw.png - kayleeFrye_onDeck
@kayleeFrye_onDeck - 是的,它是/曾经是Directx9 SDK的一部分。 - Fraser

1
使用Delphi代码,您可以在待机过程中检测无效的监视器几何形状:
i := 0
('Monitor'+IntToStr(i)+': '+IntToStr(Screen.Monitors[i].BoundsRect.Left)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Top)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Right)+', '+
IntToStr(Screen.Monitors[i].BoundsRect.Bottom))

结果:

待机前监视器几何:

Monitor0: 0, 0, 1600, 900

在Delphi 7中待机时监测显示器的几何形状:

Monitor0: 1637792, 4210405, 31266576, 1637696

在DelphiXE中待机时监视几何图形:

Monitor0: 4211194, 40, 1637668, 1637693

1
这是一篇很旧的帖子,但如果能帮助到某些人,我找到了一个解决方案来检测屏幕是否可用:Windows的连接和配置显示(CCD)API。

它是User32.ddl的一部分,有趣的函数是GetDisplayConfigBufferSizesQueryDisplayConfig。它给我们所有可以在Windows配置面板中查看的信息。

特别是PathInfo包含一个TargetInfo属性,其中有一个targetAvailable标志。这个标志似乎在我尝试过的所有配置中都被正确更新。

这使您可以知道连接到PC的每个屏幕的状态并设置它们的配置。

这里是.Net的CCD包装器


3
连接单个Dell显示器通过DisplayPort到Windows 10电脑对我没有起作用。无论显示器的电源状态是什么,targetAvailable始终为1。但还是感谢您分享您的结果。 - Greg

1
我在表单中添加了一个 VCL 定时器来检查监视器状态。
对于单个监控系统,这对我很有效。希望能对其他人有所帮助。
function GetDevicePowerState(hDevice: DWORD; var pfOn: BOOL): BOOL; stdcall;
external kernel32;

function CheckMonitorState: boolean;
var
Hwnd: THandle;
Stat: LongBool;
begin
Hwnd := CreateFile('\\.\LCD', 0, 0, nil, OPEN_EXISTING, 0, 0);
if Hwnd <> INVALID_HANDLE_VALUE then
  GetDevicePowerState(Hwnd, Stat);
Result := Stat;
CloseHandle(Hwnd);
end;

procedure TForm1.Timer2Timer(Sender: TObject);
begin
  if CheckMonitorState then
  Memo1.Lines.Append('Monitor ON')
  else
    Memo1.Lines.Append('Monitor OFF');
end;

0

如果您的显示器有某种内置的USB集线器,您可以尝试使用它来检测显示器的开/关状态。
当然,这只有在USB集线器在显示器被认为“关闭”时不保持连接时才有效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接