Windows 8.1上的WndProc奇怪行为:仅在调用伪printf时才有效

时间:2015-08-25 19:30:41

标签: c windows winapi

  

更新: @JonathanPotter在评论中解决了我的问题(见下文)。显然我应该在DefWindowProc上致电WndProc。如果我将其称为虚拟printf,那么一切正常。但是我会保持这个问题的开放,因为我仍然很想知道为什么printf本身也让它起作用。

我正在编写一个程序,可以在打开/关闭笔记本电脑盖时执行某些操作。有一个不可见的窗口,可以监视WM_POWERBROADCAST个消息并正确处理它们。还有一个控制台(用于调试目的)。

该程序在Windows 10上运行正常,然后我在另一台运行Windows 8.1的计算机上进行测试,但该程序未捕获WM_POWERBROADCAST消息。

奇怪的是:

  • 如果我将虚拟 printf添加到WndProc的开头,会收到消息

我准备了一个MCVE,以防有人想尝试重现它(下面)。请注意,printf的开头有WndProc评论。

场景1:printf行仍然被评论

如果我在Windows 10上运行程序,这就是我运行时得到的结果(无需关闭盖子,只需运行程序):

Power broadcast message received

但如果我在Windows 8.1上运行它,我什么也得不到(即使我关闭/打开盖子)。

场景2:printf行未注释

这就是我两者 Windows 10和8.1:

MSG: 36
MSG: 129
MSG: 131
MSG: 1
MSG: 799
MSG: 536
Power broadcast message received
MSG: 49273

MSG: 49273除外,它没有出现在Windows 8.1上,但似乎没有相关性。)

为什么会这样?

更多信息:

  • 两个Windows都是64位
  • 编译器:MinGW 64 5.1.0(x86_64-posix-seh-rev0)

以下是MCVE

#include <windows.h>
#include <stdio.h>

int WndProc(HWND hWnd, UINT message,
            WPARAM wParam, LPARAM lParam)
{
    //printf("MSG: %d\n", message);

    if (message == WM_POWERBROADCAST)
    {
        printf("Power broadcast message received\n");
    }
}

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
    WNDCLASS wc;
    memset(&wc, 0, sizeof(WNDCLASS));
    wc.lpfnWndProc = (WNDPROC)WndProc;
    wc.lpszClassName = L"Test";

    RegisterClass(&wc);

    HWND hWnd = CreateWindow(wc.lpszClassName, NULL,
        0, 0, 0, 0, 0, NULL, NULL,
        hInstance, NULL);

    RegisterPowerSettingNotification(hWnd, &GUID_LIDSWITCH_STATE_CHANGE, 0);

    ShowWindow(hWnd, SW_HIDE);

    MSG msg;
    while (GetMessage(&msg, NULL, 0, 0))
    {
        TranslateMessage(&msg);
        DispatchMessage(&msg);
    }
    return msg.wParam;
}

提前致谢。

1 个答案:

答案 0 :(得分:4)

问题是WndProc返回了一些东西而你没有返回任何东西。虚拟printf的奇怪行为是由于你的printf返回的伪像在eax寄存器中遗留下来,导致它成为函数返回。

当添加默认值:return DefWindowProc(...)时,这会满足大多数消息的返回值,所以WM_POWERBROADCAST突然开始工作。

失败的最可能解释是你的unilitialized返回变成了WM_NCCREATE或WM_CREATE的失败代码,因此窗口没有被创建。