Search code examples
c++editorwin32guiwndprocwinmain

Does my main window receive edit controls upon creation or when I click on the update region?


I am very new to Win32 so please be gentle as I am surely not describing my question well at all, but am extremely serious about learning more. So, I have modified my main window to include the option to edit, both write and delete, text, but in order to feel comfortable moving forward, I need to know where exactly the main window knew to create the edit controls.

Are the edit controls creation part of the CreateWindowEx that creates the main window? Or are they only created when I click on the update region that then informs my WM_CREATE case to begin the second CreateWindowEx that actually includes the Edit Styles that enable the controls? This is the only way I can make the order of things make sense, but I need to make sure I'm not just jumping at the first "logical" conclusion. Is my theory correct or completely wrong?

#include <Windows.h>
#include "resource.h"


LPCWSTR g_szClassName{ L"My Window Class" };

LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) {
    switch (msg) {
    case WM_CREATE:
    {
        HFONT hfDefault;
        HWND hEdit;

        hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, L"Edit", L"",
            WS_CHILD | WS_VISIBLE | WS_VSCROLL | WS_HSCROLL |
            ES_MULTILINE | ES_AUTOVSCROLL | ES_AUTOHSCROLL,
            0, 0, 100, 100,
            hwnd, (HMENU)IDC_MAIN_EDIT, GetModuleHandle(NULL), NULL);
        if (hEdit == NULL) {
            MessageBox(hwnd, L"Could not create edit box.", L"Error!", MB_OK | MB_ICONERROR);
        }

        hfDefault = (HFONT)GetStockObject(DEFAULT_GUI_FONT);
        SendMessage(hEdit, WM_SETFONT, (WPARAM)hfDefault, MAKELPARAM(FALSE, 0));

    break;
    }
    case WM_SIZE:
    {
        HWND hEdit;
        RECT rcClient;

        GetClientRect(hwnd, &rcClient);

        hEdit = GetDlgItem(hwnd, IDC_MAIN_EDIT);
        SetWindowPos(hEdit, NULL, 0, 0, rcClient.right, rcClient.bottom, SWP_NOZORDER);

    break;
    }
    case WM_CLOSE:
        DestroyWindow(hwnd);
        break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wParam, lParam);
    }
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
    LPSTR lpCmdLine, int nCmdShow)
{
    WNDCLASSEX wc;
    HWND hwnd;
    MSG Msg;

    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = 0;
    wc.lpfnWndProc = WndProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 32, 32, 0);
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1);
    wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU1);
    wc.lpszClassName = g_szClassName;
    wc.hIconSm = (HICON)LoadImage(hInstance, MAKEINTRESOURCE(IDI_ICON1), IMAGE_ICON, 32, 32, 0);

    if (!RegisterClassEx(&wc)) {
        MessageBox(NULL, L"Windows registration failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
    }

    hwnd = CreateWindowEx(
        WS_EX_CLIENTEDGE,
        g_szClassName,
        L"The title of my window",
        WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 240, 120,
        NULL, NULL, hInstance, NULL);

    if (hwnd == NULL) {
        MessageBox(NULL, L"Windows registration failed!", L"Error!",
            MB_ICONEXCLAMATION | MB_OK);
    }

    ShowWindow(hwnd, nCmdShow);
    UpdateWindow(hwnd);

    while (GetMessage(&Msg, NULL, 0, 0) > 0) {
        TranslateMessage(&Msg);
        DispatchMessage(&Msg);
    }

    return Msg.wParam;
}

Solution

  • Before CreateWindow/Ex() exits, it sends a WM_CREATE message (among several other mesages) to the window that is being created. CreateWindow/Ex() does not exit until all of those messages have been processed (unless an error occurs).

    So, by the time CreateWindowEx() in your main() has exited, your main window has been fully created, including any child controls that its WM_CREATE handler creates.