Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

CreateWindowEx function fails but GetLastError() returns ERROR_SUCCESS

I am trying to create a simple window with C/C++ using the native Windows message queue system (without .NET). I followed the MSDN tutorial and wrote some basic code that creates an empty window:

void main()
    {
    HINSTANCE hinst;
    HWND hwndMain;
    WNDCLASSEX wnd;
    MSG msg;

    hinst = GetModuleHandle( NULL );
    memset( &wnd, 0, sizeof( wnd ) );
    wnd.cbSize = sizeof( wnd );
    wnd.lpszClassName = "MainWClass";
    wnd.lpfnWndProc = MainWProc;
    wnd.hInstance = hinst;
    int result = RegisterClassEx( &wnd );
    if( !result )
    {
        printf("RegisterClassEx error: %d\r\n", GetLastError() );
    }

    hwndMain = CreateWindowEx
        (
        0, //extended styles
        wnd.lpszClassName, //class name
        "Main Window", //window name
        WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MINIMIZEBOX, //style tags
        CW_USEDEFAULT, //horizontal position
        CW_USEDEFAULT, //vertical position
        CW_USEDEFAULT, //width
        CW_USEDEFAULT, //height
        (HWND) NULL, //parent window
        (HMENU) NULL, //class menu
        (HINSTANCE) wnd.hInstance, //some HINSTANCE pointer
        NULL //Create Window Data?
        );

    if( !hwndMain )
    {
        printf("Oh shi- %d\n", GetLastError() );
    }
    ShowWindow( hwndMain, SW_SHOWDEFAULT );
    UpdateWindow( hwndMain );
}

When I run/debug the program, CreateWindowEx returns 0 which means it failed. This triggers the error message "Oh shi- [error code]". The most confusing part is that the error message prints to console:

Oh shi- 0

The error code returned by GetLastError() is 0, which is ERROR_SUCCESS!

I am at a total loss; what is happening? I am so confuse...

P.S. I am using Visual C++ Express 2010 on Windows 7 32-bit. I have written a Windows Procedure elsewhere but it simply returns 0 for all cases. If, however, anyone wants to see it, I will be happy to show it.

I have changed the Project Default character set of my Visual C++ project to "Not Set". I should not need to prefix L to my things.

Edit: added wnd.hInstance = hinst;

Edit: removed the unnecessary (WNDPROC) cast

Edit: added error checking for RegisterClassEx

It turns out that the problem was with Visual C++ Express (or at least not with the code itself). I copied the code to another project and it worked.

like image 349
Joshua Avatar asked Dec 18 '11 08:12

Joshua


1 Answers

wnd.lpfnWndProc = (WNDPROC) MainWProc;

We can't see the real reason you need to use the cast but it is very fishy. Windows returns 0 from GetLastError() if it didn't see anything going wrong. Which can happen if the window procedure is broken. Like this one:

LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    return 0;
}

Windows sends the WM_NCCREATE message to ask for the window to be created. If that message doesn't get processed then there will be no window. And no error. Fix:

LRESULT CALLBACK MainWProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
   return DefWindowProc(hWnd, uMsg, wParam, lParam);
}

Tweak as necessary to customize the window. Just make sure that DefWindowProc() gets called for every message that you don't want to handle yourself. And keep Petzold close at hand to avoid the simple mistakes. And lose the cast.

like image 181
Hans Passant Avatar answered Sep 26 '22 18:09

Hans Passant