100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
C++

Drawing with CDC

A practical tour of the CDC drawing API — lines, shapes, text, and pens/brushes — and the conventions MFC applications follow to render correctly inside OnDraw and OnPaint.

GraphicsBeginner9 min readJul 10, 2026
Analogies

The CDC Drawing Surface

CDC is the workhorse class for all 2D drawing in MFC: it exposes methods like MoveTo/LineTo for line segments, Rectangle, Ellipse, and Polygon for shapes, and TextOut/DrawText for strings. In a document/view application, CView::OnDraw(CDC* pDC) is the single place where all normal rendering happens — it's called both for screen repaints and, transparently, for print previews and actual printing, because the same CDC-derived pointer is substituted with a printer DC during those operations.

🏏

Cricket analogy: Like a single batting technique that works whether Rohit Sharma is facing a net bowler in practice or a fast bowler in a World Cup final, OnDraw's drawing code runs unchanged whether pDC targets the screen or the printer.

Drawing Lines, Shapes, and Filled Regions

CDC::MoveTo sets the current position without drawing; LineTo then draws a segment from that position to the given point and updates the current position, letting you chain calls to build polylines. Rectangle, RoundRect, Ellipse, and Polygon all use the DC's currently selected pen for the outline and currently selected brush for the fill — Polygon in particular respects the DC's polygon fill mode (ALTERNATE or WINDING), which matters when drawing self-intersecting shapes like a star.

🏏

Cricket analogy: Like a fielder's relay throw going from the boundary to the keeper via a designated cut-off man, each MoveTo sets the 'current position' and the following LineTo relays the line onward from there, chaining into a polyline.

Drawing and Formatting Text

TextOut draws a string at a fixed logical position using the DC's currently selected font, background mode (opaque or transparent via SetBkMode), and text color (SetTextColor). DrawText is more flexible: given a CRect and format flags like DT_CENTER, DT_VCENTER, or DT_WORDBREAK, it handles alignment and word wrapping for you, which is why it's the preferred choice for labels inside dynamically sized rectangles rather than fixed coordinates.

🏏

Cricket analogy: Like a scoreboard operator manually placing the score digits at fixed pixel positions versus an automated system that centers and resizes text within a fixed panel, TextOut places text at exact coordinates while DrawText auto-fits text within a CRect.

cpp
void CMyView::OnDraw(CDC* pDC)
{
    CMyDoc* pDoc = GetDocument();

    // Draw a polyline
    pDC->MoveTo(10, 10);
    pDC->LineTo(100, 10);
    pDC->LineTo(100, 80);

    // Draw a filled ellipse using current pen/brush
    CBrush brush(RGB(200, 220, 255));
    CBrush* pOldBrush = pDC->SelectObject(&brush);
    pDC->Ellipse(120, 10, 220, 90);
    pDC->SelectObject(pOldBrush);

    // Draw centered, word-wrapped text inside a rectangle
    CRect rect(10, 100, 220, 160);
    pDC->SetBkMode(TRANSPARENT);
    pDC->DrawText(_T("Rendered identically on screen and printer"),
                  &rect, DT_CENTER | DT_VCENTER | DT_WORDBREAK);
}

Clipping and Invalidating the Right Region

OnDraw is invoked with a clip region already established from the invalid rectangle Windows computed, so drawing outside that area is simply discarded — but it still costs CPU time to compute, so well-behaved views call Invalidate(FALSE) with a specific CRect via InvalidateRect rather than blindly invalidating the whole client area whenever only a small part of the view actually changed. GetClipBox lets drawing code query the current clip rectangle to skip expensive drawing work entirely outside it.

🏏

Cricket analogy: Like a TV director only cutting to the replay camera covering the specific boundary rope where the ball actually landed rather than every camera around the ground, InvalidateRect limits redraw work to just the changed region.

GetClipBox returns the bounding rectangle of the current clip region as a CRect. A common performance pattern is to check whether an object's bounding rectangle intersects that clip box before doing any expensive drawing math for it — this is especially valuable in views with hundreds of drawable items, where most objects fall entirely outside the small area that actually needs repainting.

  • CView::OnDraw(CDC* pDC) is the single rendering entry point shared by screen display, print preview, and printing.
  • MoveTo sets the current position without drawing; LineTo draws from the current position and advances it, enabling chained polylines.
  • Rectangle, Ellipse, and Polygon use the DC's currently selected pen for outlines and brush for fills.
  • TextOut draws at a fixed logical coordinate; DrawText handles alignment and word wrapping within a given CRect.
  • SetBkMode and SetTextColor control how text backgrounds and glyph color are rendered.
  • Invalidate/InvalidateRect should target only the changed region rather than the whole client area for performance.
  • GetClipBox lets drawing code skip expensive work for objects entirely outside the current clip region.

Practice what you learned

Was this page helpful?

Topics covered

#MFCMicrosoftFoundationClassesStudyNotes#MicrosoftTechnologies#DrawingWithCDC#Drawing#CDC#Surface#Lines#StudyNotes#SkillVeris#ExamPrep