-1

编辑- 添加了与最初未包含的 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”的结果呢?

4

1 回答 1

1

问题不在于 m_hWndFrame 是否为 NULL,而在于 m_hWndClient 是否为 NULL。

在 MDI 客户端窗口的WM_CREATE处理程序中WndProc创建并将其句柄存储在m_hWndClient. 任何未处理的消息都会进入末尾的行WndProc

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

但是WM_CREATE,这不是发送到窗口的第一条消息(WM_NCCREATE之前发送WM_CREATE)。因此,当之前 收到一条消息时WM_CREATEm_hWndClient仍然未初始化并且是一个无效的窗口句柄,如错误消息所示。

因此,在这种情况下,初始化 m_hWndFrame 在技术上不是必需的,但初始化 m_hWndClient 否则 DefFrameProc 调用会为客户端窗口的句柄获取垃圾。

于 2013-05-22T21:17:37.313 回答