我希望我的应用程序在屏幕被锁定时(Win 7和10)运行一些代码。当用户锁定屏幕时,我的应用程序也可能在后台。
有人指出我正确的方向吗?
谢谢你, 中继员
答案 0 :(得分:2)
使用WTSRegisterSessionNotification()
注册HWND
,以通过WM_WTSSESSION_CHANGE
窗口消息接收WTS_SESSION_(UN)LOCK
通知。
您可以使用FMX的FormToHWND()
函数来获取表单的HWND
。但是,FireMonkey控件(包括窗体)没有像VCL那样具有可覆盖的WndProc()
方法来处理窗口消息,因此您将必须使用Win32 API的SetWindowLongPtr()
或SetWindowSubclass()
函数(请参见MSDN上的Subclassing Controls)以接收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