This tutorial guides you through the essential steps of creating a basic window using the Win32 API for desktop application development. Understanding window creation is fundamental to building any graphical user interface on Windows.

Core Concepts

Creating a window involves several key components:

Step-by-Step Guide

1. Include Necessary Headers

You'll need to include the primary Win32 header file:

#include <windows.h>

2. Define the Window Procedure

This function is the heart of your window's interaction. It receives messages and acts upon them.

LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
    switch (message) {
        case WM_DESTROY:
            PostQuitMessage(0);
            return 0;
        default:
            return DefWindowProc(hWnd, message, wParam, lParam);
    }
}

The example above handles only the WM_DESTROY message, which is sent when the user closes the window. DefWindowProc handles all other messages.

3. Register the Window Class

Use the WNDCLASSEX structure to define your window class properties and then register it using RegisterClassEx.

WNDCLASSEX wc = {0};
wc.cbSize = sizeof(WNDCLASSEX);
wc.lpfnWndProc = WndProc;          // Pointer to the window procedure
wc.hInstance = hInstance;        // Handle to the instance that creates the window
wc.lpszClassName = L"MyWindowClass"; // The name of the window class
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1); // Window background color
wc.hCursor = LoadCursor(NULL, IDC_ARROW);   // Default cursor
wc.hIcon = LoadIcon(NULL, IDI_APPLICATION); // Default application icon
wc.hIconSm = LoadIcon(NULL, IDI_APPLICATION); // Small application icon

if (!RegisterClassEx(&wc)) {
    // Handle registration error
    return 1;
}

The hInstance parameter is typically obtained from the WinMain function's arguments.

4. Create the Window

Use CreateWindowEx to create an instance of the window. This function requires numerous parameters to define the window's appearance and behavior.

HWND hWnd = CreateWindowEx(
    0,                              // Extended window style
    L"MyWindowClass",               // Class name
    L"My First Window",             // Window title
    WS_OVERLAPPEDWINDOW,            // Window style
    CW_USEDEFAULT, CW_USEDEFAULT,   // Position x, y
    CW_USEDEFAULT, CW_USEDEFAULT,   // Size width, height
    NULL,                           // Parent window
    NULL,                           // Menu
    hInstance,                      // Instance handle
    NULL                            // Additional application data
);

if (!hWnd) {
    // Handle window creation error
    return 1;
}

5. Show the Window and Enter the Message Loop

Use ShowWindow and UpdateWindow to display the window. The message loop processes events.

ShowWindow(hWnd, nCmdShow);
UpdateWindow(hWnd);

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

nCmdShow is also provided by the WinMain function and determines how the window is initially displayed.

Putting It All Together (WinMain)

The entry point for a Win32 application is the WinMain function.

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    // ... (Register Window Class code from step 3) ...

    // ... (Create Window code from step 4) ...

    // ... (Show Window and Message Loop code from step 5) ...

    return (int)msg.wParam;
}
Important: The L"..." syntax denotes wide character strings (UTF-16), which are standard for Win32 API functions. Ensure your project is configured for Unicode.

Common Window Styles

Further Exploration