Question

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'?

Was it helpful?

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.

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