我正在尝试创建一个简单的窗口,但我遇到了一些问题。编译器不会给出错误,但它根本无法创建窗口的hWnd。它还说“msg”变量在没有被初始化的情况下被使用。这不是一个错误,只是一个警告,但我觉得不舒服。当我点击调试屏幕中的hWnd表时,它说“未使用的CXX0030:错误:表达式无法评估”。这是代码:
#include <windows.h>
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
HWND hWnd;
MSG msg;
WNDCLASSEX wcex;
ZeroMemory(&wcex, sizeof(WNDCLASSEX));
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WndProc;
wcex.cbClsExtra = 0;
wcex.cbWndExtra = 0;
wcex.hInstance = hInstance;
wcex.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wcex.hCursor = LoadCursor(NULL, IDC_ARROW);
wcex.hbrBackground = (HBRUSH)COLOR_BACKGROUND;
wcex.lpszMenuName = NULL;
wcex.lpszClassName = "Breakout_Test";
wcex.hIconSm = NULL;
if(!RegisterClassEx(&wcex))
return 0;
hWnd = CreateWindowEx(NULL, "Breakout_Test", "Breakout Test (DirectX 9)", WS_OVERLAPPEDWINDOW,
0, 0, 640, 480, NULL, NULL, hInstance, NULL);
ShowWindow(hWnd, nCmdShow);
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
switch(message)
{
case WM_CLOSE:
PostQuitMessage(0);
break;
default:
DefWindowProc(hWnd, message, wParam, lParam);
}
return 0;
}
答案 0 :(得分:6)
你的消息循环都错了。编译器非常正确,您没有初始化msg
。我不确定你从哪里得到那个消息循环。这是标准的:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
如果您想使用基于非阻塞PeekMessage
的循环,这似乎是DirectX应用程序的常用循环,它可能如下所示:
PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE);
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// game code here
}
}
请注意,我们在进入msg
循环之前初始化while
,以测试msg.message
。
你的另一个大问题是你的窗口程序。您不会返回从DefWindowProc
返回的值。 default
处理程序应如下所示:
return DefWindowProc(hWnd, message, wParam, lParam);
您的破窗程序是CreateWindowEx
失败的原因。破窗口程序是CreateWindowEx
的经典故障模式之一。
进行这两项更改,您的程序将正常运行。
对于像雷米这样的人,他们担心GetMessage
returns -1
when it fails,Raymond Chen explains why you don't need to worry about that这一事实,至少对于这个消息循环而言。
答案 1 :(得分:1)
未初始化的变量确实是一个警告,你应该感到不舒服,因为警告是正确的。在为msg.message
分配任何内容之前,请检查WM_QUIT
是否为msg
。
您必须进行更多调试才能找到创建窗口句柄的失败;该问题不包括任何有关该问题的信息 - 甚至没有表明此类问题正在检查。
无法在调试器中检查变量可能是由于优化器在不再使用它之后删除了有关它的信息。 ShowWindow
返回后,无需维护hWnd
变量。继续在代码中使用它,您可能会在调试器中看到它的寿命更长。
答案 2 :(得分:1)
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}
应该是:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
默认值应为: 返回DefWindowProc(hWnd,message,wParam,lParam);
此外,我不确定这是否会有所作为,但我认为它会:
定义msg
时,它应该是:
MSG msg = { };
或
MSG msg = {0};
答案 3 :(得分:0)
您的default
条款错误。虽然它确实调用了DefWindowProc
,但它无法返回其返回值。发送到WndProc
的第一封邮件之一是WM_NCCREATE
。由于您无条件地return 0;
(又名FALSE
)窗口创建停止并且CreateWindowEx
返回NULL。