2

The following is a portion of my code. Every time I run the program, CreateWindowEx of the SPanel returns NULL, triggering an error. Can anyone see what is wrong with this piece of code?

SPanelProc and MainWndProc are declared already, and is of the prototype LRESULT CALLBACK SPanelProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);.

The environment I'm programming in is Visual C++ 2010.

Why is CreateWindowEx always returning NULL?

#include <Windows.h>
#include <WindowsX.h>

LRESULT CALLBACK SPanelProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
    switch (msg)
    {
        case WM_MOUSEMOVE:

        break;
    }

    return 0;
}

void Init ()
{
    HWND child;
    HINSTANCE hInstance = (HINSTANCE)(GetWindowLongPtr (parent, GWLP_HINSTANCE));
    WNDCLASSEX wc;
    const char PanelClassName[] = "SPanel"; //ClassName of the panel. Do not reuse on another window

    //Create the window, initialize GWLP_USERDATA, check for errors, register the window class, and hide the window


    //Create the windowclass for the button
    wc.cbSize        = sizeof (WNDCLASSEX);
    wc.style         = 0;
    wc.lpfnWndProc   = SPanelProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon (hInstance, IDI_APPLICATION);
    wc.hCursor       = LoadCursor (hInstance, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName  = NULL;
    wc.lpszClassName = PanelClassName;
    wc.hIconSm       = LoadIcon (hInstance, IDI_APPLICATION);

    //If could not register window class
    if(!RegisterClassEx (&wc))
    {
        MessageBox (NULL, "Panel registration failed!", "Error!", MB_OK);
        PostQuitMessage (0);
        return;
    }

    //Create window
    child = CreateWindowEx (WS_EX_NOPARENTNOTIFY, PanelClassName, "TITLE_TEXT", WS_CHILD, 0, 0, 400, 200, parent, NULL, hInstance, NULL);

    //Check for error in window creation
    if (child == NULL)
    {
        MessageBox (NULL, "Panel creation failed!", "Error!", MB_OK);
        PostQuitMessage (0);
        return;
    }

    return;
}


int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hWnd;
    MSG Msg;
    int length, width;

    //Register the window, create the window, and check for errors
    {
        //Window class
        wc.cbSize        = sizeof (WNDCLASSEX);
        wc.style         = 0;
        wc.lpfnWndProc   = MainWndProc;
        wc.cbClsExtra    = 0;
        wc.cbWndExtra    = 0;
        wc.hInstance     = hInstance; //Instance used to create the window
        wc.hIcon         = LoadIcon (hInstance, MAKEINTRESOURCE (IDI_CODERICON)); //Change here to change large application icon
        wc.hCursor       = LoadCursor (hInstance, IDC_ARROW); //Change here to change application cursor
        wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); //Change here to change starting background color (white)
        wc.lpszMenuName  = NULL;
        wc.lpszClassName = Coder::Constants::MAINWNDCLASSNAME;
        wc.hIconSm       = (HICON)LoadImage (hInstance, MAKEINTRESOURCE (IDI_CODERICON), IMAGE_ICON, GetSystemMetrcs (SM_CXSMICON), GetSystemMetrics (SM_CYSMICON), 0); //Change here to change application icon (small, as in taskbar)

        //Register the window class so that the ClassName can be used to create the window and then check for error
        if (!RegisterClassEx (&wc))
        {
            MessageBox (NULL, "Main window registration failed!", "Error!", MB_OK);
            return 0;
        }

        //Get screen dimensions
        length = GetSystemMetrics (SM_CXSCREEN);
        width = GetSystemMetrics (SM_CYSCREEN);

        //Create window
        hWnd = CreateWindowEx (WS_EX_CLIENTEDGE, /*Border*/
            Coder::Constants::MAINWNDCLASSNAME,
            Coder::Constants::MAINWNDTITLETEXT, /*Title of window*/
            WS_OVERLAPPED | WS_SYSMENU | WS_MINIMIZEBOX | WS_THICKFRAME | WS_CLIPCHILDREN, /*Window style*/
            (length - Coder::Constants::XDEFAULT - Coder::Constants::XSHIFT) / 2, (width - Coder::Constants::YDEFAULT - Coder::Constants::YSHIFT) / 2, /*Top-left x and y coordinates*/
            Coder::Constants::XDEFAULT + Coder::Constants::XSHIFT, Coder::Constants::YDEFAULT + Coder::Constants::YSHIFT, /*Lengths and widths of window*/
            NULL, NULL, 
            hInstance, NULL);

        //Check for error in window creation
        if (hWnd == NULL)
        {
            MessageBox (NULL, "Main window creation failed!", "Error!", MB_OK);
            return 0;
        }
    }

    //Call function
            Init (hWnd);

    //Show and redraw the window
    ShowWindow (hWnd, nCmdShow);
    UpdateWindow (hWnd);

    //Put window in message loop
    while (GetMessage (&Msg, NULL, 0, 0) > 0) //While not terminated
    {
        TranslateMessage (&Msg);
        DispatchMessage (&Msg);
    }

    //Return
    return static_cast<int>(Msg.wParam);
}
GILGAMESH
  • 1,816
  • 3
  • 23
  • 33
  • 2
    How does `SPanelProc()` handle `WM_NCCREATE` and `WM_CREATE`? Does it return `TRUE` when handling `WM_NCCREATE` and `0` when handling `WM_CREATE`? – Frédéric Hamidi Jun 19 '12 at 17:08
  • 2
    Where does *parent* come from? Does it belong to another process? That's not possible. – Hans Passant Jun 19 '12 at 17:14
  • 2
    Can you include some output from GetLastError? You might be able to use it to diagnose your problem. http://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx – Wug Jun 19 '12 at 17:15
  • 1
    Try `GetLastError` and `FormatMessage` to potentially get some info on why it's failing. Usually it's because you have an invalid parameter like conflicting styles etc. – AJG85 Jun 19 '12 at 17:16
  • 1
    I suspect an error in your wnd proc. Can you post that code? – i_am_jorf Jun 19 '12 at 17:32
  • SPanelProc () does not handle the mentioned messages. GetLastError () returned a DWORD with value 0. I have updated the code to be more complete. Thank you for helping and looking over this complicated code. – GILGAMESH Jun 19 '12 at 17:48

1 Answers1

10

Every window procedure MUST return DefWindowProc(hwnd,msg,wparam,lparam) on every message, with exceptions on messages like WM_ERASEBKGND and WM_PAINT when you are using your custom painting procedure (you must return 0 so the OS doesn't the repaint the window with it's default procedure)

lazy_banana
  • 450
  • 5
  • 10
  • Yes, that was the reason. I thought I could finalize the creation and then deal with the WndProc, but it looks like that is not true. Thank you all! I have upvoted everyone and mark you as the answer. – GILGAMESH Jun 19 '12 at 18:23