Introduction

Welcome back to Drawing with Windows GDI. We have reached Lesson 3, so our window already knows how to enter the paint cycle and draw styled shapes with custom pens and brushes. In this lesson, we will make that canvas more informative by adding text that sits exactly where we want it. By the end, we will control text color, remove the solid background behind the letters, and place a Unicode caption under our graphics with TextOutW.

How Text Fits Into GDI

Before we touch the code, it helps to build the right mental model. As you may recall from previous units, shapes get their look from the active pen and brush. Text is different: it uses its own visual settings, even though it still draws through the same HDC.

  1. SetTextColor chooses the color of the letters.
  2. SetBkMode decides whether text gets a painted background.
  3. TextOutW places the string at exact coordinates.

This separation is very useful; it lets us keep the shapes red and blue, while the caption becomes purple and blends neatly into the scene.

Returning To The Paint Cycle

The outer structure stays familiar. We still include the Windows API header, process messages in the window procedure, and perform drawing inside WM_PAINT. That continuity is important, because text belongs to the same repaint flow as every other visual element.

BeginPaint gives us the HDC that all GDI drawing functions will use in this repaint. It also tells Windows that we are actively handling the invalid region. If we want text to reappear correctly after the window is covered, resized, or refreshed, it must be drawn here, just like the Rectangle and Ellipse from the earlier lessons.

Recreating The Styled Scene

Before placing the caption, we rebuild the same styled drawing environment from the previous lesson. In this lesson, we intentionally move the shapes into a side-by-side layout near the top so there is a clean strip of space available for the caption underneath them. The shapes become our reference points.

The pen creates a red outline, and the brush creates a blue fill. After SelectObject, both shapes use that active style automatically. Notice the coordinates: both shapes sit in the upper part of the client area, with their bottom edge at y = 120. That detail matters soon, because we will place the text just beneath them. We also save the old pen and brush so the device context can be restored later.

Setting Text Color And Background

Now we switch from shape styling to text styling. Even though the same HDC is still active, text does not use the pen color or brush fill. Instead, we set its appearance through dedicated text functions.

SetTextColor makes the letters purple by combining red and blue, while leaving green at zero. SetBkMode(hdc, TRANSPARENT) is especially important for clean overlays: it tells GDI to draw only the characters themselves. In other words, Windows will not paint an opaque rectangle behind the text. If you do need a solid background for a label, you can use SetBkMode(hdc, OPAQUE) combined with SetBkColor(hdc, RGB(...)) to specify the fill color.

Preparing A Wide String

With the text style ready, we need the actual content. The code stores it as a wide character string, which matches the W version of the drawing function that we will call next.

There are two details worth noticing here. First, wchar_t is the character type used for wide strings on Windows. Second, the L prefix turns the string literal into a wide string literal. That makes it compatible with TextOutW, which expects Unicode-style text input. Using the wide version keeps our code aligned with modern Windows API usage and avoids mixing character encodings.

Placing Text With Precision

This is the key step of the lesson: we draw the string at a very specific position. The text is not just displayed somewhere on the screen; it is placed so it visually belongs to the shapes above it.

TextOutW uses the HDC, the starting x and y coordinates, the text buffer, and the character count. The x value of 50 lines up with the left edge of the Rectangle. The y value of 130 places the text just below the shapes, since their bottom edge is at 120, and 130120=10130 - 120 = 10. gives the visible character count, not the null terminator. Because the shapes were drawn first, this caption appears as a clear purple label beneath them.

Restoring Objects And Ending Paint

Even though this lesson focuses on text, the GDI object lifecycle still matters. Once the drawing is done, we restore the original tools, delete the ones we created, and close the paint cycle properly.

This follows the same safe pattern from the previous lesson: restore first, then delete only what we created. We do not delete hOldPen or hOldBrush, because those objects were returned by the system and are not ours to destroy. EndPaint completes the repaint operation, and return 0; tells Windows that WM_PAINT has been fully handled.

Conclusion and Next Steps

In this lesson, we extended our canvas from pure shapes to a more complete composition. We recreated the styled Rectangle and Ellipse, gave text its own purple color, set the background mode to TRANSPARENT, stored the caption as a wide string, and used TextOutW with lstrlenW to place it precisely under the graphics. We also kept the paint cycle and message flow correct, which is what makes the result reliable during real window updates.

Next, the practice tasks will let us place labels with confidence and sharpen the small positioning decisions that make GDI drawings feel intentional and polished.

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