Writing Your First Win32 Application with C++

Welcome to the first windows tutorial. In this tutorial, I’ll give you the basic information on how to code in windows and we’ll go over a few important details first.

Messages

The basic windows program has two important functions inside. The first one is the event handler(I’ll talk about this one later on) and the second one is the main function(WinMain from now on). WinMain is similar to DOS’ main function, in fact, WinMain is called from the DOS main function but in windows, we don’t have access to the DOS main; everything is covered up by windows. Windows introduces us to messages. A message could be easily described as a pile of data that gets sent to the event handler which then tells the window what to do. A message’s name is prefixed with WM(stands for Windows Message as you might have guessed?). There are a whole lot of messages that a window can handle, however, we’ll only need a few of them. You can use these messages in many ways. For example, the message WM_CREATE, can be used for initialization purposes, it gets sent to the window when it’s created, and WM_PAINT is used when you want to draw something on the screen, and so on, you get the image. Most of the messages get sent to the window automatically; for example, when you move your mouse around you send a message to windows, and any other actions like that send messages to windows. You can also send a message to your window yourself, but you’ll probably never need to.

Handles

Handles in windows. You will see a lot of these when programming a windows program. Handles are basically usual integers and they are used as identifiers to identify all kinds of stuff. Handles are usually prefixed with an H. For example, HICON is a handle to the icon that your window will use, very simple. Other handles include HDLG - to a dialog box, HWND - to a window, HMENU - to a menu.

The Big Picture

In your Windows program, the first thing you want to think about is the event handler(sometimes called message handler) function. This is the first function that you want to write in your code; it’s your windows program starting point. As I said above, the event handler function takes care of all the messages that the window might send to it. After that you’ll write your WinMain function; that’s where you take care of the window class structure and finally create the window. The following text contains information on what should be done in a basic WinMain function.

The Window Class

You will need to know the structure of the window class because you have to fill it in before creating the window itself. There are two window class structures WNDCLASS, and WNDCLASSEX. They are basically the same, the only difference is that WNDCLASS is slowly becoming outdated, if it hasn’t already. Obviously, you’ll want to use the EX one and it looks like this:

typedef struct _WNDCLASSEX {
  UINT cbSize; // size of this structure in bytes
  UINT style; // style of the class
  WNDPROC lpfnWndProc; // pointer to the message handler f-n
  int cbClsExtra; // always 0
  int cbWndExtra; // always 0
  HINSTANCE hInstance; // handle to the main instance
  HICON hIcon; // which icon to show
  HCURSOR hCursor; // which cursor image to use
  HBRUSH hbrBackground; // the window background color
  LPCTSTR lpszMenuName; // you can attach a menu with this one
  LPCTSTR lpszClassName; // string, specifies the class name
  HICON hIconSm; // which small icon to use
}
WNDCLASSEX;

The truth is: that you will need to fill the above structure with some info before creating any window. After you’re done with that you will need to register for this class. To register a class you make a call to RegisterClassEx(&ex_class), you have to pass the pointer of the structure to it. If you decided to use WNDCLASS instead of WNDCLASSEX for some reason, just use RegisterClass(&class) (without the Ex at the end).

Creating the Window

After that, you’re ready to create your window. In our case, you create a window with CreateWindowEx, which takes a chunk of parameters. Don’t be intimidated by the long list; most of the time you only care about a handful of them: the class name you just registered, the window’s title, its style, and its position and size on screen. The rest can be left as defaults (we’ll pass NULL or 0). Here’s the function prototype:

HWND CreateWindowEx(DWORD dwExStyle, // window extended style
  LPCTSTR lpClassName, // class name
  LPCTSTR lpWindowName, // window name
  DWORD dwStyle, // window style
  int x, // x and y position
  int y,
  int nWidth, // width
  int nHeight, // height
  HWND hWndParent, // handle to parent window
  HMENU hMenu, // handle to menu
  HINSTANCE hInstance, // handle to instance of window
  LPVOID lpParam); // pointer to window creation data

The Message Loop

Once the window is created, you show it with ShowWindow and kick off the main event loop. The event loop is what keeps your program alive: it sits in a while loop pulling messages out of the queue with GetMessage and dispatching them to your event handler, until the user closes the window.

The Event Handler

We saved the most important function for last. The event handler, often called the window procedure, is where your window actually reacts to the world; every message the loop dispatches ends up here. Its signature is fixed:

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

uMsg is the message ID (one of those WM_ values), while wParam and lParam carry data specific to each message. Inside, you switch on uMsg and write a case only for the messages you care about, handing everything else to DefWindowProc for its standard default behavior. This is the function whose address you stored in lpfnWndProc when filling in the window class; that pointer is how Windows knows where to deliver the messages.

Putting It Together

If you’re still piecing together the order of things, here’s the whole skeleton at a glance:

  • Write the event handler
  • Write WinMain()
  • Fill in the class info
  • Register the class
  • Call CreateWindowEx() to create the window
  • Write the main event loop

A Complete Example

And here’s an example of a sample application:

#include <windows.h>

// Prototype of the windows procedure function
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
  // Design a window class
  WNDCLASSEX wndcls;
  wndcls.cbSize = sizeof(WNDCLASSEX);
  wndcls.style = CS_HREDRAW | CS_VREDRAW;
  wndcls.lpfnWndProc = WindowProc;
  wndcls.cbClsExtra = 0;
  wndcls.cbWndExtra = 0;
  wndcls.hInstance = hInstance;
  wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
  wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);
  wndcls.hbrBackground = (HBRUSH) GetStockObject(WHITE_BRUSH);
  wndcls.lpszMenuName = NULL;
  wndcls.lpszClassName = "Win32Application";
  wndcls.hIconSm = LoadIcon(NULL, IDI_APPLICATION);

  // Register the window class
  RegisterClassEx(&wndcls);

  // Create a window
  HWND hwnd = CreateWindowEx(0, "Win32Application", "Windows Application", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, NULL, NULL, hInstance, NULL);

  // Show the window and update it
  ShowWindow(hwnd, SW_SHOWNORMAL);
  UpdateWindow(hwnd);

  // Start the event loop
  MSG msg;
  while (GetMessage(&msg, NULL, 0, 0)) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);
  }

  return (int) msg.wParam;
}

// Windows procedure function
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {
  switch (uMsg) {
  case WM_CREATE:
    // Initialize the window
    break;
  case WM_PAINT: {
    // Paint the window's client area
    PAINTSTRUCT ps;
    HDC hDC = BeginPaint(hwnd, &ps);
    const char *text = "Welcome to the Win32 programming world!";
    TextOut(hDC, 0, 0, text, lstrlen(text));
    EndPaint(hwnd, &ps);
    break;
  }
  case WM_CLOSE:
    if (MessageBox(hwnd, "Are you sure to quit?", "Message", MB_YESNO) == IDYES)
      DestroyWindow(hwnd);
    break;
  case WM_DESTROY:
    // Clean up window-specific data objects
    PostQuitMessage(0);
    break;
  default:
    // Process other messages
    return DefWindowProc(hwnd, uMsg, wParam, lParam);
  }

  return 0;
}

How the Sample Works

Let’s walk through what this sample does, from top to bottom.

Designing and registering the class. Inside WinMain we fill in a WNDCLASSEX structure with the fields we discussed above: the background brush, the cursor and icon, the instance handle, and most importantly lpfnWndProc, which points at our event handler WindowProc. We give the class a name ("Win32Application") so we can refer to it later, then hand it to RegisterClassEx.

Creating and showing the window. CreateWindowEx takes the class name we just registered and produces an actual window, returning its handle (HWND). The window won’t appear on screen until we call ShowWindow; UpdateWindow then forces an immediate WM_PAINT so the client area is drawn right away.

The message loop. GetMessage blocks until a message arrives, then we hand it off: TranslateMessage turns raw key presses into readable character messages, and DispatchMessage routes the message to WindowProc. The loop keeps running until GetMessage returns 0, which happens when a WM_QUIT message shows up. That’s our cue to exit.

Handling messages. WindowProc is where the window comes to life. Every message we care about gets its own case:

  • WM_CREATE fires once, right when the window is born, a good spot for one-time initialization.
  • WM_PAINT is sent whenever the client area needs redrawing. We wrap our drawing between BeginPaint and EndPaint, and use TextOut to write a line of text at the top-left corner.
  • WM_CLOSE fires when the user clicks the close button. Here we pop up a confirmation box and only call DestroyWindow if they choose Yes.
  • WM_DESTROY fires as the window is torn down. We call PostQuitMessage, which posts the WM_QUIT that finally breaks our message loop.

Any message we don’t explicitly handle is passed to DefWindowProc, which gives it the standard default behavior. This is what makes the window draggable, resizable, and so on, without us writing a single line for it.

Building and running. Compile this as a Win32 (GUI) project, for example with Visual Studio, or g++ main.cpp -o app.exe -mwindows under MinGW. One catch: the plain string literals above assume a multi-byte build, so if your project defaults to Unicode (as modern Visual Studio does) wrap each one in the TEXT(...) macro — e.g. TEXT("Win32Application") — or switch the project’s character set to Use Multi-Byte Character Set. Run it and you’ll get a 640×480 white window titled Windows Application, with the line Welcome to the Win32 programming world! drawn in the top-left corner. Click the close button and you’ll see the confirmation dialog before the program quits.

Wrapping Up

That’s your first complete Win32 application: register a class, create a window, pump messages, and respond to the ones you care about. Almost every native Windows program, no matter how large, is built on this exact skeleton.