C:\msys64\ucrt64\include
// Register the window class.
const wchar_t CLASS_NAME[]  = L"Sample Window Class";
 
WNDCLASS wc = { };
 
wc.lpfnWndProc   = WindowProc;
wc.hInstance     = hInstance;
wc.lpszClassName = CLASS_NAME;
RegisterClass(&wc);

HWND hwnd = CreateWindowEx(
    0,                              // Optional window styles.
    CLASS_NAME,                     // Window class
    L"Learn to Program Windows",    // Window text
    WS_OVERLAPPEDWINDOW,            // Window style
 
    // Size and position
    CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT,
 
    NULL,       // Parent window    
    NULL,       // Menu
    hInstance,  // Instance handle
    NULL        // Additional application data
    );
 
if (hwnd == NULL)
{
    return 0;
}

CreateWindowEx() parameters:

  1. Window Behavior. 0 for default behavior.
  2. Name of Window Class.
  3. Window Text. Displayed in the title bar.
  4. Window Style.
  5. Position/Size. CW_USEDEFAULT for default values.
  6. Parent/Owner Window.
  7. Window Menu.
  8. Instance Handle.
  9. Additional app data

MSG msg; 
GetMessage(&msg, NULL, 0, 0);

GetMessage() removes a the topmost message from the message queue.
It then assigns it to the &msg structure if the function succeeds.
The other three parameters are used for filtering messages.

If there are no messages, then the program has simply nothing to do.

GetMessage() returns a non-zero value.
When a function PostQuitMessage() is called, it sends a message WM_QUIT which makes GetMessage() return 0.

MSG msg = { };
while (GetMessage(&msg, NULL, 0, 0) > 0) {
	TranslateMessage(&msg);
	DispatchMessage(&msg);
}

LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

WindowProc() arguments

  • hwnd is the window handle.
  • uMsg is the message code.
  • wParam and lParam for additional info depends on the uMsg

Programs are built as a large switch statement, where the program switches depends on the uMsg.
To make code modular, pass the wParam and lParam into the correct data type, then pass those to a function.

Unhandled messages? Pass those to this line of code:

return DefWindowProc(hwnd, uMsg, wParam, lParam);

Note: UI doesn’t respond and accept any messages until the procedure request completes. To fix this, utilize multithreading to keep processing in the background.