Определить блокировку экрана - FMX в Win32 - PullRequest
0 голосов
/ 02 декабря 2018

Я хочу, чтобы мое приложение запускало некоторый код, когда экран заблокирован (Win 7 и 10).Мое приложение может быть в фоновом режиме, когда пользователь блокирует экран.

Кто-нибудь указывает мне правильное направление?

Спасибо, ретранслятор

1 Ответ

0 голосов
/ 02 декабря 2018

Используйте WTSRegisterSessionNotification() для регистрации HWND для получения WTS_SESSION_(UN)LOCK уведомлений через оконное сообщение WM_WTSSESSION_CHANGE.

Вы можете использовать функцию FMX FormToHWND() для получения формы HWND.Однако элементы управления FireMonkey, включая формы, не имеют переопределяемого метода WndProc() для обработки оконных сообщений, как это делает VCL, поэтому вам придется использовать функцию SetWindowLongPtr() или SetWindowSubclass() Win32 API (см. Элементы управления подклассами в 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

В качестве альтернативы, вы можете использовать функцию 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
...