Edit-添加了与m_hWndClient和WndProc有关的代码,这些代码最初不包括在内。为了简短起见,我错误地认为这是无关的。
执行以下命令后,运行
HWND m_hWndFrame;
HWND m_hWndClient; // added in Edit2
...
m_hWndFrame = CreateWindowEx(...)
m_hWndFrame
为NULL, GetLastError
给出"错误1400 -无效窗口句柄",但这工作得很好:
HWND m_hWndFrame = NULL;
HWND m_hWndClient = NULL; // added in Edit2
...
m_hWndFrame = CreateWindowEx(...)
我的WndProc
是这样的:
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);
}
我的项目现在工作(经过许多头发撕裂),但我不明白为什么初始化一个变量,只用于保存返回值应该重要。
显然假设一个变量是NULL或0没有初始化,然后使用或测试的内容(如if (!m_unitialisedVariable)
)将在灾难中结束,但为什么它应该在这种情况下重要?在调用"CreateWindowEx"之前,没有要求m_hWndFrame
包含任何特别的东西(至少根据VS2010中的帮助),那么为什么它应该影响"CreateWindowEx"的结果呢?
问题不在于m_hWndFrame是否为NULL,而在于m_hWndClient是否为NULL。
在WndProc
的WM_CREATE
处理程序中创建了一个MDI客户端窗口,并将其句柄存储在m_hWndClient
中。任何未处理的消息都将通过WndProc
末尾的行:
return DefFrameProc(hwnd,m_hWndClient,uMsg,wParam,lParam);
然而WM_CREATE
不是发送到窗口的第一个消息(WM_NCCREATE
在WM_CREATE
之前发送)。因此,当在 WM_CREATE
之前收到消息时,m_hWndClient
仍然未初始化,并且是错误消息所指示的无效窗口句柄。
所以在这个实例中初始化m_hWndFrame在技术上是没有必要的,但是初始化m_hWndClient否则DefFrameProc调用会为客户端窗口的句柄获取垃圾。