我希望我的应用程序在屏幕被锁定时运行一些代码(Win 7和10) . 当用户锁定屏幕时,我的应用程序也可能在后台 .
有人指出我正确的方向吗?
谢谢你,接力员
使用WTSRegisterSessionNotification()注册 HWND 以通过WM_WTSSESSION_CHANGE窗口消息接收 WTS_SESSION_(UN)LOCK 通知 .
HWND
WTS_SESSION_(UN)LOCK
您可以使用FMX的FormToHWND()函数来获取表单的 HWND . 但是,FireMonkey控件(包括Forms)没有可覆盖的 WndProc() 方法来处理窗口消息,如VCL,因此您必须使用Win32 API的 SetWindowLongPtr() 或 SetWindowSubclass() 函数(请参阅MSDN上的Subclassing Controls)来接收 WM_WTSSESSION_CHANGE 窗口消息:
WndProc()
SetWindowLongPtr()
SetWindowSubclass()
WM_WTSSESSION_CHANGE
class TMyForm : public TForm { ... #ifdef _Windows private: bool MonitoringWTS; static LRESULT CALLBACK SubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData); protected: virtual void __fastcall CreateHandle(); #endif ... };
#ifdef _Windows #include <FMX.Platform.Win.hpp> #include <commctrl.h> #include <wtsapi32.h> void __fastcall TMyForm::CreateHandle() { MonitoringWTS = false; TForm::CreateHandle(); // depending on which version of C++Builder you are using... HWND hWnd = FormToHWND(this); //HWND hWnd = WindowHandleToPlatform(Handle)->Wnd; //HWND hWnd = FmxHandleToHWND(Handle); if (!SetWindowSubclass(hWnd, &SubclassWndProc, 1, reinterpret_cast<DWORD_PTR>(this))) throw Exception(_D("Could not subclass window")); MonitoringWTS = WTSRegisterSessionNotification(hWnd, NOTIFY_FOR_THIS_SESSION); if (!MonitoringWTS) RaiseLastOSError(); } LRESULT CALLBACK TMyForm::SubclassWndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData) { switch (uMsg) { case WM_NCDESTROY: { WTSUnRegisterSessionNotification(hWnd); reinterpret_cast<TMyForm*>(dwRefData)->MonitoringWTS = false; RemoveWindowSubclass(hWnd, &SubclassWndProc, uIdSubclass); break; } case WM_WTSSESSION_CHANGE: { TMyForm *pThis = reinterpret_cast<TMyForm*>(dwRefData); switch (wParam) { case WTS_SESSION_LOCK: // do something ... break; case WTS_SESSION_UNLOCK: // do something ... break; } return 0; } } return DefSubclassProc(hWnd, uMsg, wParam, lParam); } #endif
或者,您可以使用RTL的AllocateHWnd()函数创建隐藏的 HWND 并为其提供自定义 WndProc() 方法:
class TMyForm : public TForm { ... #ifdef _Windows private: HWND WndForWTS; bool MonitoringWTS; void __fastcall WndProcForWTS(TMessage &Message); public: __fastcall TMyForm(TComponent *Owner); __fastcall ~TMyForm(); #endif ... };
#ifdef _Windows #include <wtsapi32.h> __fastcall TMyForm::TMyForm(TComponent *Owner) : TForm(Owner) { WndForWTS = AllocateHWnd(&WndProcForWTS); MonitoringWTS = WTSRegisterSessionNotification(WndForWTS, NOTIFY_FOR_THIS_SESSION); if (!MonitoringWTS) { int err = GetLastError(); DeallocateHWnd(WndForWTS); RaiseLastOSError(err); } } __fastcall ~TMyForm(); { DeallocateHWnd(WndForWTS); } void __fastcall TMyForm::WndProcForWTS(TMessage &Message) { switch (Message.Msg) { case WM_NCDESTROY: { if (MonitoringWTS) { WTSUnRegisterSessionNotification(WndForWTS); MonitoringWTS = false; } WndForWTS = NULL; break; } case WM_WTSSESSION_CHANGE: { switch (Message.WParam) { case WTS_SESSION_LOCK: // do something ... break; case WTS_SESSION_UNLOCK: // do something ... break; } return; } } Message.Result = DefWindowProc(WndForWTS, Message.Msg, Message.WParam, Message.LParam); } #endif
1 回答
使用WTSRegisterSessionNotification()注册
HWND
以通过WM_WTSSESSION_CHANGE窗口消息接收WTS_SESSION_(UN)LOCK
通知 .您可以使用FMX的FormToHWND()函数来获取表单的
HWND
. 但是,FireMonkey控件(包括Forms)没有可覆盖的WndProc()
方法来处理窗口消息,如VCL,因此您必须使用Win32 API的SetWindowLongPtr()
或SetWindowSubclass()
函数(请参阅MSDN上的Subclassing Controls)来接收WM_WTSSESSION_CHANGE
窗口消息:或者,您可以使用RTL的AllocateHWnd()函数创建隐藏的
HWND
并为其提供自定义WndProc()
方法: