I am trying to create a simple window, but I had some problem. Compiler won't give error, but it simply can't create the hWnd of the window. Also it says that "msg" variable is being used without being initialized. It is not an error, just a warning, however I feel uncomfortable. It says "unused CXX0030: Error: expression cannot be evaluated" when I click to the hWnd table in the debug screen. Here is the code:
#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;
}
Your message loop is all wrong. The compiler is quite right that you are not initializing msg
. I'm not sure where you got that message loop from. Here's the standard one:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
If you want to use a non-blocking PeekMessage
based loop which seems popular for DirectX applications, it might look like this:
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
}
}
Notice that we initialise msg
before entering the while
loop which tests msg.message
.
Your other big problem is in your window procedure. You don't return the value that you get back from DefWindowProc
. The default
handler should look like this:
return DefWindowProc(hWnd, message, wParam, lParam);
Your broken window procedure is the reason why CreateWindowEx
fails. A broken window procedure is one of the classic failure modes for CreateWindowEx
.
Make these two changes and your program will work.
For people like Remy, who are worried about the fact that GetMessage
returns -1
when it fails , Raymond Chen explains why you don't need to worry about that , at least for this message loop.
The uninitialized variable is indeed a warning, and you should feel uncomfortable, because the warning is correct. You check whether msg.message
is WM_QUIT
before you've assigned anything to msg
.
You'll have to do more debugging to find out about the failure to create a window handle; the question doesn't include any information about that — not even an indication that such a problem is being checked for.
The inability to inspect the variable in the debugger could be due to the optimizer removing information about it after it's no longer used. Once ShowWindow
returns, there's no need to maintain the hWnd
variable. Continue using it in your code, and you might see it live longer in the debugger.
while(msg.message != WM_QUIT)
{
if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
}
}
Should be:
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
The default should be: return DefWindowProc(hWnd, message, wParam, lParam);
Also, I am not sure if this would make a difference, but I think it would: When you define msg
it should be:
MSG msg = { };
or
MSG msg = {0};
Your default
clause is wrong. While it does call DefWindowProc
it fails to pass its return value back. One of the first messages sent to your WndProc
is WM_NCCREATE
. Since you unconditionally return 0;
(aka FALSE
) window creation stops and CreateWindowEx
returns NULL.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.