One of the functions used most often in MFC development is Invalidate(). But are you calling it carelessly every time you just want to redraw the screen? Based on the material I was given, here's a rundown of the core ideas behind the 'Dirty Flag pattern,' which cuts down on unnecessary redraws and maximizes performance.

1. What Invalidate() Really Means: "A Signal That the Screen Has Become Invalid"

Invalidate() is not a command that says "redraw the screen right now!" It's an act of marking — a request that says, "the data in this region has changed and is no longer valid, so please redraw it (WM_PAINT) whenever the OS gets a free moment."

Core principle: The OS treats any region on which Invalidate() has been called as being 'Dirty,' and later, once the message queue has some slack, it fires off a WM_PAINT message to actually perform the redraw.

2. The Key to Performance: The Dirty Flag Pattern

If you call Invalidate() excessively even when the data hasn't changed, the CPU ends up repeating unnecessary OnPaint operations. This is where using a Dirty Flag (a flag indicating whether a redraw is needed) can dramatically improve performance.

Dirty Flag implementation logic:
  1. Detect a data change → set bIsDirty = true.
  2. Call Invalidate() only when the data has actually changed.
  3. After OnPaint() finishes processing → reset it back to bIsDirty = false.

Example Code: Efficient Redrawing Using a Flag

void CMyView::UpdateData(int nNewValue) {
    if (m_nData != nNewValue) { // Only when the value has actually changed
        m_nData = nNewValue;
        m_bIsDirty = true;      // Set the Dirty Flag
        Invalidate();           // Only now request a redraw
    }
}

void CMyView::OnPaint() {
    CPaintDC dc(this);
    if (m_bIsDirty) {
        // Perform the actual drawing logic
        m_bIsDirty = false;    // Clear the flag once the redraw is done
    }
}

3. A Word of Caution: Invalidate vs UpdateWindow

This is a point developers often get confused about. You need to use each one correctly depending on the situation.

  • Invalidate(): "Redraw it whenever." (asynchronous — queues a message)
  • UpdateWindow(): "Redraw it right now!" (synchronous — forcibly sends WM_PAINT immediately)

When data updates happen repeatedly, it's far more efficient to use only Invalidate() and let the OS batch the redraws together.

Wrapping Up

What separates a skilled MFC UI developer from a novice comes down to "how sparingly you use Invalidate()." Adopt the Dirty Flag pattern to track data changes, and experience smooth Windows programming free of screen flickering!