1

我正在使用 Windows 7 和 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 分钟不活动后设置屏幕保护程序时,它不起作用,自动监视器屏幕关闭也是如此。这就是我想要的,知道系统何时关闭屏幕或设置屏幕保护程序,带有后台监控程序。

我也尝试过将钩子事件与 extern dll 一起使用。我已经按照这个示例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_SCREENSAVE wParam。在这种情况下,我不知道为什么,也许我错了,但这似乎不是真的。

在使用所有可能的消息到 SetWindowsHookEx 之后,我意识到 WH_GETMESSAGE 是唯一发送 SC_SCREENSAVE wParam 的人,至少在 Windows 7 中的这个钩子示例中是这样。

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

其次,监听钩子函数中捕获的每条消息,WM_SYSCOMMAND 与 LPMSG 一起出现。我还读过 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 回答