Search code examples
c++winapihwnd

Can't create HWND


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;
}

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.