当显示器重新激活时,我该如何接收通知?当显示器再次开启时,我没有收到WM_SYSCOMMAND消息。

5
我需要跟踪显示器进入睡眠状态和从睡眠状态(节能模式)唤醒的情况。
Private Const SC_MONITORPOWER = &HF170&
Private Const MONITOR_OFF = 2&
Private Const MONITOR_ON = -1&
Private Const MONITOR_STANDBY = 1&

以下是我的子类代码:

If (uMsg = WM_SYSCOMMAND) Then
    If (wParam = SC_MONITORPOWER) Then
        If (lParam = MONITOR_OFF) Then
            'I do receive this event!
            Debug.Print("Monitor is turned off")
        ElseIf (lParam = MONITOR_ON) Then
            Stop 'This is never called
        Else
            Stop 'This is never called
        End If
    End If
End If

如果显示器进入睡眠状态,将广播WM_SYSCOMMAND消息。

但是,当显示器再次开启(例如通过移动鼠标)时,我没有收到WM_SYSCOMMAND消息。

我该如何跟踪显示器何时重新激活/开启?

我做错了什么吗?

谢谢!

1个回答

5
根据文档
在WM_SYSCOMMAND消息中,wParam参数的四个低位被系统内部使用。当测试wParam值时,应用程序必须使用按位与运算符将值0xFFF0与wParam值结合,才能获得正确结果。
如果您没有这样做,那么在检测到SC_MONITORPOWER 时,可能无法正确地检测显示器是否已开启,如果其他系统标志也出现在wParam中,则可能出现此问题。
请尝试使用以下方法:
If (uMsg = WM_SYSCOMMAND) Then
    If ((wParam And &HFFF0) = SC_MONITORPOWER) Then
        If (lParam = MONITOR_OFF) Then
            Debug.Print("Monitor is turned off")
        ElseIf (lParam = MONITOR_ON) Then
            Debug.Print("Monitor is turned on")
        Else
            Debug.Print("Monitor is on standby")
        End If
    End If
End If

更新: 然而,由于您说在监视器开启时甚至没有收到WM_SYSCOMMAND消息,因此这是无意义的。 在这种情况下,请尝试注册电源事件(Registering for Power Events),请求接收更改通知,可以选择GUID_MONITOR_POWER_ONGUID_CONSOLE_DISPLAY_STATE(仅限 Win8+):

GUID_CONSOLE_DISPLAY_STATE

6FE69556-704A-47A0-8F24-C28D936FDA47

当前显示器的显示状态已更改。

Windows 7、Windows Server 2008 R2、Windows Vista 和 Windows Server 2008:此通知从 Windows 8 和 Windows Server 2012 开始提供。

Data 成员是一个 DWORD,具有以下值之一。

0x0 - 显示已关闭。

0x1 - 显示已打开。

0x2 - 显示已变暗。

GUID_MONITOR_POWER_ON

02731015-4510-4526-99E6-E5A17EBD1AEA

主系统监视器已开启或关闭。 此通知对于主动渲染内容到显示设备(例如媒体可视化)的组件非常有用。 这些应用程序应注册此通知,并在监视器关闭时停止渲染图形内容以减少系统功耗。 Data 成员是指示当前监视器状态的 DWORD。

0x0 - 显示器已关闭。

0x1 - 显示器已打开。

Windows 8 和 Windows Server 2012:新应用程序应使用 GUID_CONSOLE_DISPLAY_STATE,而不是此通知。

您的窗口将随后接收到 WM_POWERBROADCAST(PBT_POWERSETTINGCHANGE) 消息,每当请求的监视器状态更改时。


谢谢你的回复,但是按照你的方法,我无法再收到SC_MONITOR事件了。wParam为61808。只有在显示器关闭时才会收到1个WM_SYSCOMMAND消息。所以我的问题还没有得到解答。我将把我的发现添加到问题中。 - tmighty
1
61808(0xF170)是“SC_MONITORPOWER”。 (61808 And &HFFF0) = 61808,因此当wParam = 61808时,“If ((wParam And &HFFF0) = SC_MONITORPOWER) Then”应该评估为True。无论如何,这是无关紧要的,因为您刚才说在打开监视器时甚至没有收到“WM_SYSCOMMAND”消息。您昨天没有说过这一点。 - Remy Lebeau
1
是的,你说得对,它被评估为真。就像你所说的那样:当显示器打开时,我甚至没有收到WM_SYSCOMMAND。这就是我的问题。我以为我的代码“ ElseIf(lParam = MONITOR_ON)Then Stop'这从未被调用 否则 Stop'这从未被调用 结束如果”表明了这一点。现在我看到它并不是很清楚。 - tmighty

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