如何在 VB6 中定义 POWERBROADCAST_SETTING?
How do I define POWERBROADCAST_SETTING in VB6?
我想检测监控状态。
为此,我注册了 WM_POWERBROADCAST
消息。
此消息的lParam
包含PBT_POWERSETTINGCHANGE
。
typedef struct {
GUID PowerSetting;
DWORD DataLength;
UCHAR Data[1];
} POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;
GUID
在VB6中是这样定义的:
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
怎么样
DWORD DataLength;
UCHAR Data[1];
要翻译成 VB6?
POWERBROADCAST_SETTING
结构的UCHAR Data[1]
成员表示依赖于PowerSetting
和DataLength
成员的字节数组。根据 docs,Data
成员可以是 GUID 或 DWORD。所以在VB6中最简单的方法是为固定成员声明一个结构,然后根据PowerSetting
成员在第二步中获取剩余数据。
Public Type Guid
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type PowerBroadcastSetting
PowerSetting As Guid
DataLength As Long
End Type
window 过程应该如下所示:
Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim g As Guid
Dim L As Long
Dim pbs As PowerBroadcastSetting
Select Case iMsg
Case WM_POWERBROADCAST
Select Case wParam
Case PBT_APMPOWERSTATUSCHANGE
DebugPrint "PBT_APMPOWERSTATUSCHANGE"
Case PBT_APMRESUMEAUTOMATIC
DebugPrint "PBT_APMRESUMEAUTOMATIC"
Case PBT_APMRESUMESUSPEND
DebugPrint "PBT_APMRESUMESUSPEND"
Case PBT_APMSUSPEND
DebugPrint "PBT_APMSUSPEND"
Case PBT_POWERSETTINGCHANGE
CopyMemory pbs, ByVal lParam, Len(pbs)
DebugPrint "PBT_POWERSETTINGCHANGE " & GuidToString(pbs.PowerSetting)
Select Case GuidToString(pbs.PowerSetting)
Case GUID_POWERSCHEME_PERSONALITY
CopyMemory g, ByVal lParam + Len(pbs), 16
DebugPrint "New power scheme: " & GuidToString(g)
Case GUID_SESSION_DISPLAY_STATUS
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Display status: " & L
Case GUID_MONITOR_POWER_ON
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Primary Monitor state: " & L
Case GUID_CONSOLE_DISPLAY_STATE
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Console Display state: " & L
End Select
End Select
'An application should return TRUE if it processes this message.
WindowProc = 1
Exit Function
End Select
'Pass message to original window proc
WindowProc = CallWindowProc(ProcOld, hWnd, iMsg, wParam, lParam)
End Function
使用了以下 API 声明:
Public Const GWL_WNDPROC As Long = (-4)
Private Const WM_POWERBROADCAST As Long = 536
Public Type Guid
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type PowerBroadcastSetting
PowerSetting As Guid
DataLength As Long
End Type
'Power status has changed.
Private Const PBT_APMPOWERSTATUSCHANGE = 10
'Operation is resuming automatically from a low-power state. This message is sent every time the system resumes.
Private Const PBT_APMRESUMEAUTOMATIC As Long = 18
'Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
Private Const PBT_APMRESUMESUSPEND As Long = 7
'System is suspending operation.
Private Const PBT_APMSUSPEND As Long = 4
'A power setting change event has been received.
Private Const PBT_POWERSETTINGCHANGE As Long = 32787
'Power Setting GUIDs
'The active power scheme personality has changed. All power schemes map to one of these personalities.
'The Data member is a GUID that indicates the new active power scheme personality.
Public Const GUID_POWERSCHEME_PERSONALITY As String = "{245D8541-3943-4422-B025-13A784F679B7}"
'The display associated with the application's session has been powered on or off.
'The Data member is a DWORD with one of the following values.
'0x0 - The display is off.
'0x1 - The display is on.
'0x2 - The display is dimmed.
Public Const GUID_SESSION_DISPLAY_STATUS As String = "{2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}"
Public Const GUID_MONITOR_POWER_ON As String = "{02731015-4510-4526-99E6-E5A17EBD1AEA}"
' Windows 8 +
Public Const GUID_CONSOLE_DISPLAY_STATE As String = "{6FE69556-704A-47A0-8F24-C28D936FDA47}"
'Notifications are sent using WM_POWERBROADCAST messages with a wParam parameter of PBT_POWERSETTINGCHANGE.
Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cbCopy As Long)
Public Declare Function RegisterPowerSettingNotification Lib "user32.dll" (ByVal hRecipient As Long, PowerSettingGuid As Guid, ByVal Flags As Long) As Long
Public Declare Function UnregisterPowerSettingNotification Lib "user32.dll" (ByVal Handle As Long) As Long
Private Declare Function StringFromGUID2 Lib "ole32.dll" (rguid As Guid, ByVal lpsz As Long, ByVal cchMax As Long) As Long
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpsz As Long, pclsid As Guid) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
辅助函数:
Public Function GuidToString(g As Guid) As String
Dim L As Long
Dim b(0 To 77) As Byte
'we have space for 38 unicode chars (guid incl. brackets) + terminating zero (78 bytes)
L = StringFromGUID2(g, VarPtr(b(0)), 39)
'strip terminating 0, convert to string
GuidToString = Left(b, L - 1)
End Function
Public Function GuidFromString(ByVal gs As String) As Guid
CLSIDFromString StrPtr(gs), GuidFromString
End Function
Public Sub DebugPrint(ByVal s As String)
OutputDebugString s & vbCrLf
End Sub
VB6 中的测试表格:
Option Explicit
Private isSubclassed As Boolean
Private hScheme As Long
Private hDisplay As Long
Private hMonitor As Long
Private hConsole As Long
Private Sub cmdRegister_Click()
Unregister
Register
End Sub
Private Sub cmdUnregister_Click()
Unregister
End Sub
Private Sub Register()
ProcOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
isSubclassed = True
MsgBox "Subclassed"
'Register Power Events
hScheme = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_POWERSCHEME_PERSONALITY), DEVICE_NOTIFY_WINDOW_HANDLE)
hDisplay = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_SESSION_DISPLAY_STATUS), DEVICE_NOTIFY_WINDOW_HANDLE)
hConsole = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_CONSOLE_DISPLAY_STATE), DEVICE_NOTIFY_WINDOW_HANDLE)
MsgBox "Registered " & hScheme & " " & hDisplay & " " & hMonitor & " " & hConsole
End Sub
Private Sub Unregister()
'Unregister Power Events
If hScheme Then
UnregisterPowerSettingNotification hScheme
hScheme = 0
End If
If hDisplay Then
UnregisterPowerSettingNotification hDisplay
hDisplay = 0
End If
If hMonitor Then
UnregisterPowerSettingNotification hMonitor
hMonitor = 0
End If
If hConsole Then
UnregisterPowerSettingNotification hConsole
hConsole = 0
End If
'Unsubclass
If isSubclassed Then
SetWindowLong hWnd, GWL_WNDPROC, ProcOld
isSubclassed = False
MsgBox "Unsubclassed"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
Unregister
End Sub
编辑:
添加了 GUID_CONSOLE_DISPLAY_STATE
。
这是在 Windows 10 上用 DebugView 捕获的输出:
不活动后 Windows 的电源管理将显示器置于待机状态:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 2
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 2
15 秒后:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 0
[7752] PBT_POWERSETTINGCHANGE {02731015-4510-4526-99E6-E5A17EBD1AEA}
[7752] Primary Monitor state: 0
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 0
唤醒:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 1
[7752] PBT_POWERSETTINGCHANGE {02731015-4510-4526-99E6-E5A17EBD1AEA}
[7752] Primary Monitor state: 1
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 1
如果您手动关闭显示器,将不会有任何通知,至少对于我的硬件而言。不确定,如果在其他系统上会引发事件。
我想检测监控状态。
为此,我注册了 WM_POWERBROADCAST
消息。
此消息的lParam
包含PBT_POWERSETTINGCHANGE
。
typedef struct {
GUID PowerSetting;
DWORD DataLength;
UCHAR Data[1];
} POWERBROADCAST_SETTING, *PPOWERBROADCAST_SETTING;
GUID
在VB6中是这样定义的:
Private Type GUID
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
怎么样
DWORD DataLength;
UCHAR Data[1];
要翻译成 VB6?
POWERBROADCAST_SETTING
结构的UCHAR Data[1]
成员表示依赖于PowerSetting
和DataLength
成员的字节数组。根据 docs,Data
成员可以是 GUID 或 DWORD。所以在VB6中最简单的方法是为固定成员声明一个结构,然后根据PowerSetting
成员在第二步中获取剩余数据。
Public Type Guid
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type PowerBroadcastSetting
PowerSetting As Guid
DataLength As Long
End Type
window 过程应该如下所示:
Public Function WindowProc(ByVal hWnd As Long, ByVal iMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Dim g As Guid
Dim L As Long
Dim pbs As PowerBroadcastSetting
Select Case iMsg
Case WM_POWERBROADCAST
Select Case wParam
Case PBT_APMPOWERSTATUSCHANGE
DebugPrint "PBT_APMPOWERSTATUSCHANGE"
Case PBT_APMRESUMEAUTOMATIC
DebugPrint "PBT_APMRESUMEAUTOMATIC"
Case PBT_APMRESUMESUSPEND
DebugPrint "PBT_APMRESUMESUSPEND"
Case PBT_APMSUSPEND
DebugPrint "PBT_APMSUSPEND"
Case PBT_POWERSETTINGCHANGE
CopyMemory pbs, ByVal lParam, Len(pbs)
DebugPrint "PBT_POWERSETTINGCHANGE " & GuidToString(pbs.PowerSetting)
Select Case GuidToString(pbs.PowerSetting)
Case GUID_POWERSCHEME_PERSONALITY
CopyMemory g, ByVal lParam + Len(pbs), 16
DebugPrint "New power scheme: " & GuidToString(g)
Case GUID_SESSION_DISPLAY_STATUS
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Display status: " & L
Case GUID_MONITOR_POWER_ON
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Primary Monitor state: " & L
Case GUID_CONSOLE_DISPLAY_STATE
CopyMemory L, ByVal lParam + Len(pbs), 4
DebugPrint "Console Display state: " & L
End Select
End Select
'An application should return TRUE if it processes this message.
WindowProc = 1
Exit Function
End Select
'Pass message to original window proc
WindowProc = CallWindowProc(ProcOld, hWnd, iMsg, wParam, lParam)
End Function
使用了以下 API 声明:
Public Const GWL_WNDPROC As Long = (-4)
Private Const WM_POWERBROADCAST As Long = 536
Public Type Guid
Data1 As Long
Data2 As Integer
Data3 As Integer
Data4(0 To 7) As Byte
End Type
Private Type PowerBroadcastSetting
PowerSetting As Guid
DataLength As Long
End Type
'Power status has changed.
Private Const PBT_APMPOWERSTATUSCHANGE = 10
'Operation is resuming automatically from a low-power state. This message is sent every time the system resumes.
Private Const PBT_APMRESUMEAUTOMATIC As Long = 18
'Operation is resuming from a low-power state. This message is sent after PBT_APMRESUMEAUTOMATIC if the resume is triggered by user input, such as pressing a key.
Private Const PBT_APMRESUMESUSPEND As Long = 7
'System is suspending operation.
Private Const PBT_APMSUSPEND As Long = 4
'A power setting change event has been received.
Private Const PBT_POWERSETTINGCHANGE As Long = 32787
'Power Setting GUIDs
'The active power scheme personality has changed. All power schemes map to one of these personalities.
'The Data member is a GUID that indicates the new active power scheme personality.
Public Const GUID_POWERSCHEME_PERSONALITY As String = "{245D8541-3943-4422-B025-13A784F679B7}"
'The display associated with the application's session has been powered on or off.
'The Data member is a DWORD with one of the following values.
'0x0 - The display is off.
'0x1 - The display is on.
'0x2 - The display is dimmed.
Public Const GUID_SESSION_DISPLAY_STATUS As String = "{2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}"
Public Const GUID_MONITOR_POWER_ON As String = "{02731015-4510-4526-99E6-E5A17EBD1AEA}"
' Windows 8 +
Public Const GUID_CONSOLE_DISPLAY_STATE As String = "{6FE69556-704A-47A0-8F24-C28D936FDA47}"
'Notifications are sent using WM_POWERBROADCAST messages with a wParam parameter of PBT_POWERSETTINGCHANGE.
Public Const DEVICE_NOTIFY_WINDOW_HANDLE As Long = 0
Private Declare Sub CopyMemory Lib "kernel32.dll" Alias "RtlMoveMemory" (lpDest As Any, lpSource As Any, ByVal cbCopy As Long)
Public Declare Function RegisterPowerSettingNotification Lib "user32.dll" (ByVal hRecipient As Long, PowerSettingGuid As Guid, ByVal Flags As Long) As Long
Public Declare Function UnregisterPowerSettingNotification Lib "user32.dll" (ByVal Handle As Long) As Long
Private Declare Function StringFromGUID2 Lib "ole32.dll" (rguid As Guid, ByVal lpsz As Long, ByVal cchMax As Long) As Long
Private Declare Function CLSIDFromString Lib "ole32.dll" (ByVal lpsz As Long, pclsid As Guid) As Long
Public Declare Function SetWindowLong Lib "user32" Alias "SetWindowLongA" (ByVal hWnd As Long, ByVal nIndex As Long, ByVal dwNewLong As Long) As Long
Public Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hWnd As Long, ByVal Msg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
辅助函数:
Public Function GuidToString(g As Guid) As String
Dim L As Long
Dim b(0 To 77) As Byte
'we have space for 38 unicode chars (guid incl. brackets) + terminating zero (78 bytes)
L = StringFromGUID2(g, VarPtr(b(0)), 39)
'strip terminating 0, convert to string
GuidToString = Left(b, L - 1)
End Function
Public Function GuidFromString(ByVal gs As String) As Guid
CLSIDFromString StrPtr(gs), GuidFromString
End Function
Public Sub DebugPrint(ByVal s As String)
OutputDebugString s & vbCrLf
End Sub
VB6 中的测试表格:
Option Explicit
Private isSubclassed As Boolean
Private hScheme As Long
Private hDisplay As Long
Private hMonitor As Long
Private hConsole As Long
Private Sub cmdRegister_Click()
Unregister
Register
End Sub
Private Sub cmdUnregister_Click()
Unregister
End Sub
Private Sub Register()
ProcOld = SetWindowLong(hWnd, GWL_WNDPROC, AddressOf WindowProc)
isSubclassed = True
MsgBox "Subclassed"
'Register Power Events
hScheme = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_POWERSCHEME_PERSONALITY), DEVICE_NOTIFY_WINDOW_HANDLE)
hDisplay = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_SESSION_DISPLAY_STATUS), DEVICE_NOTIFY_WINDOW_HANDLE)
hConsole = RegisterPowerSettingNotification(hWnd, GuidFromString(GUID_CONSOLE_DISPLAY_STATE), DEVICE_NOTIFY_WINDOW_HANDLE)
MsgBox "Registered " & hScheme & " " & hDisplay & " " & hMonitor & " " & hConsole
End Sub
Private Sub Unregister()
'Unregister Power Events
If hScheme Then
UnregisterPowerSettingNotification hScheme
hScheme = 0
End If
If hDisplay Then
UnregisterPowerSettingNotification hDisplay
hDisplay = 0
End If
If hMonitor Then
UnregisterPowerSettingNotification hMonitor
hMonitor = 0
End If
If hConsole Then
UnregisterPowerSettingNotification hConsole
hConsole = 0
End If
'Unsubclass
If isSubclassed Then
SetWindowLong hWnd, GWL_WNDPROC, ProcOld
isSubclassed = False
MsgBox "Unsubclassed"
End If
End Sub
Private Sub Form_Unload(Cancel As Integer)
Unregister
End Sub
编辑:
添加了 GUID_CONSOLE_DISPLAY_STATE
。
这是在 Windows 10 上用 DebugView 捕获的输出:
不活动后 Windows 的电源管理将显示器置于待机状态:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 2
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 2
15 秒后:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 0
[7752] PBT_POWERSETTINGCHANGE {02731015-4510-4526-99E6-E5A17EBD1AEA}
[7752] Primary Monitor state: 0
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 0
唤醒:
[7752] PBT_POWERSETTINGCHANGE {6FE69556-704A-47A0-8F24-C28D936FDA47}
[7752] Console Display state: 1
[7752] PBT_POWERSETTINGCHANGE {02731015-4510-4526-99E6-E5A17EBD1AEA}
[7752] Primary Monitor state: 1
[7752] PBT_POWERSETTINGCHANGE {2B84C20E-AD23-4DDF-93DB-05FFBD7EFCA5}
[7752] Display status: 1
如果您手动关闭显示器,将不会有任何通知,至少对于我的硬件而言。不确定,如果在其他系统上会引发事件。