Question

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;
}
Was it helpful?

Solution

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.

OTHER TIPS

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top