Почему неинициализированное возвращаемое значение вызывает ошибку недопустимого дескриптора окна в CreateWindowEx?

Редактировать- Добавлен код для 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)) закончится катастрофой, но почему это должно иметь значение в этом случае? Там нет никаких требований для m_hWndFrame содержать что-то, в частности, перед вызовом CreateWindowEx (по крайней мере, в соответствии с справкой в ​​VS2010), так почему это должно влиять на результат CreateWindowEx?

1 ответ

Решение

Проблема не в том, что m_hWndFrame является или не равен NULL, а в том, является ли m_hWndClient значением NULL или нет.

в WM_CREATE обработчик в WndProc окно клиента 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 получает мусор для дескриптора окна клиента.

Другие вопросы по тегам