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