首页 文章

检测屏幕锁定 - Win32中的FMX

提问于
浏览
0

我希望我的应用程序在屏幕被锁定时运行一些代码(Win 7和10) . 当用户锁定屏幕时,我的应用程序也可能在后台 .

有人指出我正确的方向吗?

谢谢你,接力员

1 回答

  • 2

    使用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 窗口消息:

    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
    

相关问题