简体   繁体   English

检测屏幕锁定-Win32中的FMX

[英]Detect screen lock - FMX in Win32

I want my application to run some code when the screen gets locked (Win 7 and 10). 我希望我的应用程序在屏幕锁定(Win 7和10)时运行一些代码。 My application may be in the background too when user locks screen. 当用户锁定屏幕时,我的应用程序也可能在后台。

Anyone point me in right direction? 有人指出我正确的方向吗?

Thank you, relayman 谢谢中继员

Use WTSRegisterSessionNotification() to register an HWND to receive WTS_SESSION_(UN)LOCK notifications via the WM_WTSSESSION_CHANGE window message. 使用WTSRegisterSessionNotification()注册HWND以通过WM_WTSSESSION_CHANGE窗口消息接收WTS_SESSION_(UN)LOCK通知。

You can use FMX's FormToHWND() function to obtain your Form's HWND . 您可以使用FMX的FormToHWND()函数来获取表单的HWND However, FireMonkey controls, including Forms, do not have an overridable WndProc() method to process window messages, like VCL does, so you will have to use the Win32 API's SetWindowLongPtr() or SetWindowSubclass() function (see Subclassing Controls on MSDN) to receive the WM_WTSSESSION_CHANGE window message: 但是,FireMonkey控件(包括Forms)没有像VCL一样具有可重写的WndProc()方法来处理窗口消息,因此您将必须使用Win32 API的SetWindowLongPtr()SetWindowSubclass()函数(请参见MSDN上的子类化控件 )接收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

Alternatively, you can use the RTL's AllocateHWnd() function to create a hidden HWND and provide it with a custom WndProc() method: 另外,您可以使用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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM