< Previous Lesson Lesson Plan Next Lesson >

Painting and Drawing

14.1 Painting in a Window

The WM_PAINT message is sent when the system or another application makes a request to paint a portion of an application's window. The message is sent by the DispatchMessage function to a window procedure when the application obtains a WM_PAINT message from the message queue by using the GetMessage or PeekMessage functions.

A window receives this message through its WindowProc function. Windows always specifies the invalid area of any window in terms of a least bounding rectangle; hence, the entire window is not repainted.

14.1.1 When to Draw in a Window

An application draws in a window at a variety of times: when first creating a window, resizing, moving from behind another window, minimizing/maximizing, and scrolling.

Ideally, an application carries out most of its drawing operations during the processing of WM_PAINT messages. In this case, the application retrieves a display device context (DC) by calling the BeginPaint function. If drawing at any other time, it calls GetDC or GetDCEx.

14.1.2 The WM_PAINT Message

Upon receiving WM_PAINT, an application calls BeginPaint to retrieve the device context. After completing drawing, it calls EndPaint to release the DC.

BeginPaint performs the following:

14.1.3 Drawing Without the WM_PAINT Message

Useful for immediate feedback (e.g., dragging an object). The application uses GetDC, performs drawing, and then calls ReleaseDC. Usually, the window is not invalidated during this process; instead, the application manages the restoration of the previous state (often by inverting colors).

14.1.4 Window Background

The system sends WM_ERASEBKGND when BeginPaint is called. If the application passes this to DefWindowProc, the system erases the background using the class background brush (hbrBackground).


14.2 Window Coordinate System

The coordinate system is based on device units (pixels). The x-coordinates increase to the right; y-coordinates increase from top to bottom.

Applications can map between these using the MapWindowPoints function.


14.3 Window Regions


14.4 Conditions: PAINT Message Sent

14.5 Conditions: PAINT Message MAY be Sent

14.6 Conditions: PAINT Message NEVER Sent


14.7 PAINT Reference

14.7.1 InvalidateRect Function

Used to make a window or part of it invalid.

 BOOL InvalidateRect( HWND hWnd, // handle to window CONST RECT *lpRect, // rectangle coordinates BOOL bErase // erase state ); 

14.7.2 PAINTSTRUCT Structure

 typedef struct tagPAINTSTRUCT { HDC hdc; // Handle to the Device context BOOL fErase; // Erase background if true RECT rcPaint; // Rectangle to the invalidate region BOOL fRestore; // Reserved BOOL fIncUpdate; // Reserved BYTE rgbReserved[32]; } PAINTSTRUCT; 

14.8 Other GDI Text Output Functions

14.8.1 DrawText

Draws formatted text in a specified rectangle.

 int DrawText( HDC hDC, // handle to DC LPCTSTR lpString, // text to draw int nCount, // text length LPRECT lpRect, // formatting dimensions UINT uFormat // text-drawing options ); 
Value Description
DT_BOTTOM Justifies text to the bottom (used with DT_SINGLELINE).
DT_CENTER Centers text horizontally.
DT_VCENTER Centers text vertically (used with DT_SINGLELINE).
DT_WORDBREAK Breaks words automatically at the edge of the rectangle.
DT_NOCLIP Draws without clipping; slightly faster.
DT_SINGLELINE Displays text on a single line only.

14.8.2 TabbedTextOut

Writes a string expanding tabs to specified positions.

 LONG TabbedTextOut( HDC hDC, int X, int Y, LPCTSTR lpString, int nCount, int nTabPositions, CONST LPINT lpnTabStopPositions, int nTabOrigin ); 

14.9 Primitive Shapes

Includes Lines, Curves, and filled shapes (Ellipse, Chord, Pie, Polygon, Rectangles).

14.9.1 Lines

Drawn using MoveToEx (sets starting point) and LineTo (draws to ending point).

 BOOL LineTo( HDC hdc, int nXEnd, int nYEnd ); 

14.9.2 Rectangle

Outlined by the current pen and filled by the current brush.

 BOOL Rectangle(HDC hdc, int nLeft, int nTop, int nRight, int nBottom); 

14.10 Stock Objects

Pre-defined GDI objects in Windows are:

14.10.1 GetStockObject Function

The GetStockObject function retrieves a handle to one of the stock pens, brushes, fonts, or palettes.

 HGDIOBJ GetStockObject( int fnObject // stock object type ); 

fnObject: Specifies the type of stock object. This parameter can be one of the following values:

Value Meaning
BLACK_BRUSH Black brush.
DKGRAY_BRUSH Dark gray brush.
DC_BRUSH Windows 2000/XP: Solid color brush. Default is white. Change with SetDCBrushColor.
GRAY_BRUSH Gray brush.
HOLLOW_BRUSH Hollow brush (equivalent to NULL_BRUSH).
LTGRAY_BRUSH Light gray brush.
WHITE_BRUSH White brush.
BLACK_PEN Black pen.
DC_PEN Windows 2000/XP: Solid pen color. Default is white. Change with SetDCPenColor.
WHITE_PEN White pen.
ANSI_FIXED_FONT Windows fixed-pitch (monospace) system font.
ANSI_VAR_FONT Windows variable-pitch (proportional space) system font.
DEFAULT_GUI_FONT Default font for UI objects (menus/dialogs). Usually MS Sans Serif or Tahoma.
SYSTEM_FONT System font used to draw menus and controls.
DEFAULT_PALETTE Default palette consisting of static colors in the system palette.

Return Values: If the function succeeds, the return value is a handle to the requested logical object. If it fails, the return value is NULL.

Note: Use DKGRAY_BRUSH, GRAY_BRUSH, and LTGRAY_BRUSH only in windows with CS_HREDRAW and CS_VREDRAW styles to avoid pattern misalignment. It is not necessary to call DeleteObject to delete stock objects.

14.11 SelectObject

The SelectObject function selects an object into the specified device context (DC). The new object replaces the previous object of the same type.

 HGDIOBJ SelectObject( HDC hdc, // handle to DC HGDIOBJ hgdiobj // handle to object ); 
Object Creation Functions
Bitmap CreateBitmap, CreateCompatibleBitmap, CreateDIBSection (Memory DCs only).
Brush CreateBrushIndirect, CreateSolidBrush.
Font CreateFont, CreateFontIndirect.
Pen CreatePen, CreatePenIndirect.
Region CreatePolygonRgn, CreateRectRgn, CreateRectRgnIndirect.

Return Values: If the function succeeds and the object is not a region, the return value is a handle to the object being replaced. An application should always replace a new object with the original, default object after it has finished drawing.


14.12 Example

 // Select a dynamic pen color using stock objects SelectObject(hdc, GetStockObject(DC_PEN)); SetDCPenColor(hdc, RGB(0, 255, 0)); Rectangle(hdc, 0, 0, 20, 20);

// Change color to blue SetDCPenColor(hdc, RGB(0, 0, 255)); Rectangle(hdc, 0, 0, 20, 20);

// Example for Brush SelectObject(hdc, GetStockObject(DC_BRUSH)); SetDCBrushColor(hdc, 0x000000); // Black 

Summary

In this lecture, we studied painting in windows, specifically the WM_PAINT message. This message is triggered when a region becomes invalidated. We also explored:

Tips

Exercises

  1. Create a round rectangular region and paint it using a custom-created hatched brush. Write text that is clipped specifically to that region.
  2. Implement logic where pressing the left mouse button inside a specific region triggers a MessageBox confirming the click location.

Would you like me to generate the C++ code for the "round rectangular region" exercise described above?

< Previous Lesson Lesson Plan Next Lesson >