1

私はWindows7とVC++を使用しています。ビジネスは、システムがスクリーンセーバーモードまたはモニター画面オフに設定されている秒数を知ることです。これを実現するために、イベントWM_SYSCOMMANDおよびSC_SCREENSAVE、SC_MONITORPOWERをキャッチしようとしています。そのため、Visual Studio 2008でWin32プロジェクトを作成し、WndProc関数でイベントを受信して​​います。

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
    int wmId, wmEvent;
    PAINTSTRUCT ps;
    HDC hdc;

    switch (message)
    {
        case WM_SYSCOMMAND:
        {
            switch (LOWORD(wParam))
            {
                case SC_SCREENSAVE:
                {
                    FILE *fl = fopen("this_is_a_event_test.txt","a");
                    fputs("SC_SCREENSAVE\n",fl);
                    fclose(fl);
                }
                break;
                case SC_MONITORPOWER:
                {
                    FILE *fl = fopen("this_is_a_event_test.txt","a");
                    fputs("SC_MONITORPOWER\n",fl);
                    fclose(fl);
                }
                break;
                default:
                {
                }
            }
        }
            break;
    }
}

ダイアログがフォアグラウンドにある場合は正常に機能しますが、バックグラウンド(またはShowWindow関数にコメントする場合)では、イベントを手動で送信した場合にのみ機能します。

SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_SCREENSAVE, (LPARAM)2);
or
SendMessage(HWND_BROADCAST, WM_SYSCOMMAND, SC_MONITORPOWER, (LPARAM)2);

そのため、システムの電源設定で2分間操作がないとスクリーンセーバーが設定された場合は機能しません。また、自動モニター画面がオフの場合も同様です。それが私が望んでいる本物です。システムがバックグラウンド監視プログラムを使用して、画面をオフにしているときやスクリーンセーバーを設定しているときを知ってください。

また、externdllでフックイベントを使用しようとしました。この例http://www.codeproject.com/Articles/1037/Hooks-and-DLLsに従って、CALLBACK msghook()関数に上記のWndProcと同じスイッチコードを追加しました。SendMessageを使用しても機能しません。

この問題に数日立ち往生した後、インターネットやフォーラムで検索しました...他に何ができるかわかりません。誰か助けてもらえますか?

4

1 に答える 1

0

フックをきちんと使っていませんでしたが、めったにありませんでした。まず、setWindowsHookEx関数について、WH_CALLWNDPROCまたはWH_SYSMSGFILTERを使用してWM_SYSCOMMAND送信メッセージを取得してから、SC_SCREENSAVEwParamを取得する必要があることを確認しました。この場合、理由はわかりませんし、間違っているかもしれませんが、それは真実ではないようです。

SetWindowsHookExへの可能なすべてのメッセージを使用した後、少なくともWindows 7のこのフックの例では、WH_GETMESSAGEがSC_SCREENSAVEwParamを送信する唯一のメッセージであることに気付きました。

HHOOK hook;
HHOOK hook = SetWindowsHookEx(WH_GETMESSAGE,
                (HOOKPROC)msghook,
                hInst,
                0);

次に、フック機能でキャッチされたすべてのメッセージをリッスンし、LPMSGでWM_SYSCOMMANDが表示されました。比較するには、wParamを0xFFF0に組み合わせる必要があることも読みました。しかし、wParam&0xFFF0 == SC_SCREENSAVEは機能せず、wParam==SC_SCREENSAVEも機能しませんでした。この場合、唯一の方法は、WM_SYSCOMMANDとSC_SCREENSAVEの両方にLPMSGを使用することです。

static LRESULT CALLBACK msghook(UINT code, WPARAM wParam, LPARAM lParam)
{
     if(code > 0)
     {
         CallNextHookEx(hook, code, wParam, lParam);
         return 0;
     }

     LPMSG msg = (LPMSG)lParam;

     if(msg->message == WM_SYSCOMMAND)
     {
        if (msg->wParam == SC_SCREENSAVE)
        {
           MessageBoxA(NULL,L"SC_SCREENSAVE",L"SC_SCREENSAVE",MB_OK);
        }

        if (msg->wParam  == SC_MONITORPOWER)
        {
           MessageBoxA(NULL,L"SC_MONITORPOWER",L"SC_MONITORPOWER",MB_OK);
        }
     }

     return CallNextHookEx(hook, nCode, wParam, lParam);
}

また、FILEを使用してイベントをテストすることは非常に悪い考えでした。MessageBoxを使用することはそれほど良いことではないと思いますが、irを正しくテストする方法がわかりません。

于 2013-01-11T11:32:44.737 に答える