Introduction

Welcome to Interactive Controls and Layouts. We are at the very beginning of the course, and this first lesson gives our window its first real interface elements. Instead of showing only an empty frame, we will add a text label and a button, which are two of the most common controls in desktop apps.

By the end of this lesson, we will know where these controls are created, why they are treated as windows themselves, and how WinAPI uses built-in system classes such as STATIC and BUTTON to place them inside a parent window.

Controls Are Also Windows

A helpful idea to keep in mind is this: in WinAPI, a control is usually just another window with a special purpose. A label is a window that displays text; a button is a window that reacts to clicks and keyboard focus. Because of that, we create them with the same family of functions used for regular windows.

The main difference is their role. These controls are created as child windows, which means they live inside the main window and depend on it. A very common place to create them is WM_CREATE because that message arrives when the parent window is being set up and is ready to receive its child controls.

Preparing The Window Procedure

Inside the source file that defines our window procedure, we begin by including WinAPI types, declaring control IDs, and opening the WM_CREATE branch. This sets up the space where the controls will be created.

There are three important pieces here. First, #include <windows.h> brings in the WinAPI declarations we need. Second, the #define values give each control a unique ID, which helps us recognize them later when handling events. Third, GetWindowLongPtr(hwnd, GWLP_HINSTANCE) fetches the application instance handle from the parent window, and that handle is passed into CreateWindowW when we build the child controls.

Creating The Static Label

Now we create the first control: a text label. WinAPI provides the predefined class name STATIC for this job, so we do not need to register a custom class ourselves.

This call tells Windows to place a label inside the parent window.

  1. L"STATIC" selects the built-in label class, and L"Enter text below:" is the text shown to the user.
  2. WS_CHILD makes the label belong to the main window, and WS_VISIBLE makes it appear immediately.
  3. 20, 20, 150, 20 define the position and size. These numbers represent the horizontal distance from the left edge (20), the vertical distance from the top edge (20), the total width (150), and the total height (20) of the control, all measured in pixels relative to the parent window's client area. In the WinAPI coordinate system, the (0,0) origin is at the top-left, so those first two numbers define the starting point of the control, and the next two extend the rectangle from that corner.
  4. hwnd sets the parent window handle, and (HMENU)ID_LABEL_WELCOME stores the control ID.

The last NULL means we are not sending extra creation data.

Adding The Button Control

Next, we add a button with the predefined BUTTON class. This looks similar to the label and follows the same logic for placement and parenting.

Just like the label, we use WS_VISIBLE | WS_CHILD to ensure the button is visible and properly parented inside our main window. The parent is hwnd, and the button gets its own ID through (HMENU)ID_BUTTON_ACTION.

The return 0; is also important: it tells Windows that we handled WM_CREATE ourselves and that control creation completed successfully.

Closing The Window Cleanly

After the controls are created, the rest of the procedure handles shutdown. If you recall, WinAPI usually separates the idea of requesting a close from finishing the destruction, so we often handle both WM_CLOSE and WM_DESTROY.

When WM_CLOSE arrives, DestroyWindow(hwnd) starts tearing down the window. Once destruction is complete, Windows sends WM_DESTROY, and PostQuitMessage(0) tells the message loop to stop so the application can exit.

Anything we do not handle ourselves is passed to DefWindowProcW. That fallback is essential because it lets Windows apply its standard behavior for all other messages.

Conclusion and Next Steps

In this lesson, we built our first real WinAPI interface using standard controls. We saw that labels and buttons are created as child windows, that WM_CREATE is the right place to instantiate them, and that predefined classes such as STATIC and BUTTON let us create useful UI elements with only a few lines of code.

We also gave each control its own ID, used style flags to control behavior and appearance, and finished the window procedure with proper close and destroy handling. In the upcoming practice tasks, we will turn this knowledge into action and place these controls confidently on our own.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal