-1

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

Malorion
  • 508
  • 1
  • 4
  • 13
  • 2
    It is impossible to know for certain without seeing the full code, but my guess is that you are passing another uninitalized handle as the parent window. And it happens to hold NULL if and only if the previous sentence is the `NULL` assignment. – rodrigo May 21 '13 at 23:50
  • 5
    My guess is that the window procedure tries to use `m_hWndFrame` inside its `WM_CREATE` handler. Since that executes before `CreateWindowEx` returns, it is using an uninitialized variable. `CreateWindowEx` doesn't care about `m_hWndFrame`, but other parts of your code that run as part of window creation might care. – Raymond Chen May 21 '13 at 23:50
  • @RaymondChen: But even if he does that, `CreateWindowEx` will not fail unless he returns something `!= 0` from `WM_CREATE`... – rodrigo May 21 '13 at 23:52
  • @rodrigo, And if `CreateWindowEx` does not fail, it is not required to set the last error. All it says is that if it fails, `GetLastError` will provide you with more information. So something failing when it runs that does not cause it to fail can carry the error from what failed. – chris May 22 '13 at 00:06
  • 1
    Show us a complete program that demonstrates the issue. Don't make us guess. – David Heffernan May 22 '13 at 04:59
  • @RaymondChen You were on the right track. `m_hWndFrame` isn't used in the `WM_CREATE` but m_hWndClient is when the client window is created and then again in `DefFrameProc` which is where I presume the problem lies. Kinda obvious in hindsight. Your comment pointed me in the right direction. If you'd like to put a suitably worded answer, I'd be happy to mark it as the correct answer :) – Malorion May 22 '13 at 06:32

1 Answers1

1

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.

Malorion
  • 508
  • 1
  • 4
  • 13