c++windowswinapicreatewindowex

Why does uninitialised return value cause Invalid Window Handle err in CreateWindowEx?


Edit- Added code to do with m_hWndClient and the WndProc that were not originally included. In an attempt to be brief I had incorrectly assumed it was unrelated.

After the following is run

HWND m_hWndFrame;
HWND m_hWndClient; // added in Edit2
...
m_hWndFrame = CreateWindowEx(...)

m_hWndFrame is NULL and GetLastError gives "Error 1400 - Invalid Window Handle" but this works fine:

HWND m_hWndFrame = NULL;
HWND m_hWndClient = NULL; // added in Edit2
...
m_hWndFrame = CreateWindowEx(...)

My WndProc looks like this:

LRESULT CALLBACK ProgramManager::WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
    CLIENTCREATESTRUCT  clientCreate;
    HINSTANCE hInstance = GetModuleHandle(NULL);
    RECT clientRect;

    switch (uMsg)
    {
    case WM_CREATE:           
        clientCreate.hWindowMenu  = NULL;
        clientCreate.idFirstChild = IDM_FIRSTCHILD ;
        GetClientRect(hwnd,&clientRect);

        s_instance->m_hWndClient = CreateWindowEx(WS_EX_CLIENTEDGE, TEXT ("MDICLIENT"), NULL,
            WS_CHILD | WS_CLIPCHILDREN | WS_CLIPSIBLINGS, 0, 0, clientRect.right,
            clientRect.bottom, hwnd, (HMENU)ID_MDI_CLIENT, hInstance, 
            (LPVOID)&clientCreate); 

        return 0 ;

    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    }

    return DefFrameProc(hwnd,m_hWndClient,uMsg,wParam,lParam);
}

My project now works (after much hair-tearing) but I don't understand why initialising a variable that is only used to hold a return value should matter.

Obviously assuming that a variable is NULL or 0 without initialising and then using or testing the contents (eg if (!m_unitialisedVariable)) is going to end in disaster but why should it matter in this instance? There is no requirement for m_hWndFrame to contain anything in particular before calling 'CreateWindowEx' (at least according to the Help in VS2010) so why should it affect the outcome of 'CreateWindowEx'?


Solution

  • The problem does not lie with the fact that m_hWndFrame is or is not NULL but rather whether m_hWndClient is or is not NULL.

    In the WM_CREATE handler in WndProc an MDI client window is created and the handle for it stored in m_hWndClient. Any unprocessed messages go through to the line at the end of WndProc:

    return DefFrameProc(hwnd,m_hWndClient,uMsg,wParam,lParam);
    

    However WM_CREATE is not the first message sent to a window (WM_NCCREATE gets sent before WM_CREATE). So when a message is received before WM_CREATE, m_hWndClient is still uninitialised and is an Invalid Window Handle as was indicated by the error message.

    So initialising m_hWndFrame isn't technically necessary in this instance but initialising m_hWndClient is otherwise the DefFrameProc call gets garbage for the client window's handle.