【发布时间】:2014-03-07 19:44:57
【问题描述】:
我试图通过我的应用程序显示一个简单的 win32 窗口,但该窗口没有显示。程序将立即退出,因为通过消息泵发送了WM_DESTROY 消息。
以下是相关代码:
WNDCLASSEX wClass; //window class structur
wClass.hInstance = appInstance;
wClass.lpszClassName = CLASSNAME;
wClass.lpfnWndProc = WindowProc;
wClass.style = CS_HREDRAW | CS_VREDRAW;
wClass.cbSize = sizeof(WNDCLASSEX);
wClass.hIcon = NULL;
wClass.hCursor = LoadCursor(NULL, IDC_ARROW);
wClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
wClass.lpszMenuName = NULL;
wClass.hbrBackground = NULL;
wClass.cbClsExtra = 0;
wClass.cbWndExtra = 0;
if (!RegisterClassEx(&wClass))
{
Debug::getInstance().log("Faild to create Window Class", EDEBUG_LEVEL::E_ERROR);
//throw some errors
return;
}
windowHandle = CreateWindowEx(
NULL,
CLASSNAME,
title.c_str(), //real window title
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX,
position.x, position.y,
size.x, size.y,
NULL,
NULL,
appInstance,
NULL
);
if (windowHandle == NULL)
{
Debug::getInstance().log("CreateWindow failed.", EDEBUG_LEVEL::E_ERROR);
}
在此代码中,appInstance 是来自条目 WinMain 函数的 hInstance。我已经调试了这段代码,但这里似乎没有任何问题。
这是我的 WndProc:
LRESULT CALLBACK WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
// sort through and find what code to run for the message given
switch (message)
{
// this message is read when the window is closed
case WM_DESTROY:
{
// close the application entirely
PostQuitMessage(0);
return 0;
} break;
}
// Handle any messages the switch statement didn't
return DefWindowProc(hWnd, message, wParam, lParam);
}
还有我的信息泵:
while (TRUE) {
while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
TranslateMessage(&msg);
DispatchMessage(&msg);
}
if (msg.message == WM_QUIT) {
break;
}
}
调试WndProc 函数后,我发现WM_DESTROY 在WM_CREATE 和0x0090 之后发送(我不知道这是什么意思)。
我做错了什么?
哦,忘了说。在我创建我的窗口后,这也会被执行:
ShowWindow(windowHandle, SW_SHOW);
UpdateWindow(windowHandle);
SetFocus(windowHandle);
编辑:经过进一步调查,我发现问题似乎是由构造函数调用窗口构建方法引起的:
Window::Window(HINSTANCE thisInstance, DirectX::XMINT2 size, wstring title, bool enableFullscreen) :
appInstance(thisInstance),
position(0, 0),
size(size),
#ifdef UNICODE
title(title),
#else
title(string(title.begin(), title.end())),
#endif
fullscreen(false)
{
this->buildWindow();
if (fullscreen)
setFullscreenWindowed(true);
}
this->buildWindow() 是我发布的第一个代码。如果我将buildWindow() 作为另一个类的公共成员方法调用,它就可以正常工作。
这里有什么问题?它不是虚拟功能。 Window 不继承或实现另一个类。
【问题讨论】:
-
您的消息泵异常。它通常是这样的:
while(::GetMessage(&Msg, NULL, 0, 0) > 0) { ::TranslateMessage(&Msg); ::DispatchMessage(&Msg); }。您可以尝试用这个替换您现有的泵并报告结果吗? -
@AlwaysLearningNewStuff 这看起来像一个典型的游戏循环消息泵;游戏处理将在 PeekMessage() 循环之后完成。
-
@puelo - 这是你的全部代码吗?听起来 WM_DESTROY 上面的 case 语句可能缺少一个中断。
-
@HerrJoebob:在我看来也是如此,但我不确定。尽管如此,我认为没有什么是错的。也许这不是实际代码,他有
if (msg.message = WM_QUIT)而不是if (msg.message == WM_QUIT)? -
如果
PeekMessage在WM_QUIT之后在其循环中检索其他消息,那么您将错过它,使用上述逻辑。此外,如果队列中根本没有消息,那么当您进行比较时,msg可能未初始化。