handmade.network » Wiki » GUI Program Skeleton

Windows

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <windows.h>

LRESULT CALLBACK WindowProcedure(HWND window, UINT message, WPARAM wParam, LPARAM lParam) {
    if (message == WM_DESTROY) {
        // If we receive the destroy message, then quit the program.
        PostQuitMessage(0);
        return 0;
    } else {
        // We don't handle this message. Use the default handler.
        return DefWindowProc(window, message, wParam, lParam);
    }
}

int CALLBACK WinMain(HINSTANCE instance, HINSTANCE previousInstance, 
        LPSTR commandLine, int commandShow) {
    // Create the window class.
    WNDCLASS windowClass = {};
    windowClass.style = CS_HREDRAW | CS_VREDRAW;
    windowClass.lpfnWndProc = WindowProcedure;
    windowClass.hInstance = instance;
    windowClass.lpszClassName = "MyWindowClass";
    windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
    windowClass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
    RegisterClass(&windowClass);

    // Create and show the actual window.
    HWND window = CreateWindow("MyWindowClass", "Hello, GUI!", WS_OVERLAPPEDWINDOW,
        CW_USEDEFAULT, CW_USEDEFAULT, 400, 200, NULL, NULL, instance, NULL);
    ShowWindow(window, commandShow);
    UpdateWindow(window);

    // Process window messages.
    MSG message;
    while (GetMessage(&message, NULL, 0, 0) > 0) {
        TranslateMessage(&message);
        DispatchMessage(&message);
    }

    return message.wParam;
}

Link with user32.lib. Public domain license.

Linux / X11

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
// Compile with gcc this_file.c -lX11
#include <X11/Xlib.h>

int main(void){

    // Create connection to the X Server.
    Display* dpy = XOpenDisplay(NULL);

    // Create window.
    Window   win = XCreateSimpleWindow(
        dpy,
        DefaultRootWindow(dpy), // Parent
        0, 0,                   // X/Y, often overridden by window manager
        400, 200,               // Width/Height
        0, 0,                   // Border
        WhitePixel(dpy, 0)      // Background
    );

    char msg[] = "Hello, GUI!";

    // Set window title.
    XStoreName(dpy, win, msg);

    // Choose which events we want.
    XSelectInput(dpy, win,
                 SubstructureNotifyMask // Window size changes (ConfigureNotify)
                 | ExposureMask         // Window needs to be repainted (Expose)
                 | PointerMotionMask    // Mouse moves (MotionNotify)
                 | ButtonPressMask
                 | ButtonReleaseMask
                 | KeyPressMask);

    // Make window visible and give it focus.
    XMapRaised(dpy, win);

    // For window manager close button event.
    Atom win_closed_id = XInternAtom(dpy, "WM_DELETE_WINDOW", 0);
    XSetWMProtocols(dpy, win, &win_closed_id, 1);

    for (;;) {
        XEvent ev;
        XNextEvent(dpy, &ev);

        // WM close button pushed, exit.
        if (ev.type == ClientMessage && ev.xclient.data.l[0] == win_closed_id) {
            return 0;
        }

        // Expose event tells us to repaint (some of) the window.
        if (ev.type == Expose) {
            XDrawString(dpy, win, DefaultGC(dpy, 0), 30, 30, msg, sizeof(msg)-1);
        }
    }
}