Document/View Architecture
The Document/View architecture is MFC's built-in pattern for separating what an application's data is (a CDocument-derived class holding, say, a list of shapes or a text buffer) from how that data is currently being shown and edited (a CView-derived class that draws it and handles input), so the same document can in principle support multiple simultaneous views without duplicating the underlying data or its load/save logic. This split roughly predates and closely resembles the later Model-View-Controller and Model-View-ViewModel patterns used in web and modern desktop frameworks, and understanding it is essential to working with any MFC application generated through the standard AppWizard document-based project templates.
Cricket analogy: CDocument holding the raw data while CView renders it is like the official scorebook (document) recording every ball bowled, while a stadium's giant screen, a TV broadcast graphic, and a radio commentator's description are all different views of that same underlying scorecard.
CDocument: Owning the Data
A CDocument-derived class owns the application's actual data in member variables and is responsible for loading and saving it, most commonly by overriding Serialize(CArchive& ar) and using the CArchive's IsStoring() to decide whether to write with ar << member or read with ar >> member for each piece of state, letting MFC's document/view framework handle the File > Open and File > Save UI plumbing automatically. Whenever the document's data changes - a shape is added, text is edited - the document is expected to call UpdateAllViews() so that every CView currently attached to it can redraw itself to reflect the new state, which is the mechanism that keeps multiple simultaneous views of the same document in sync.
Cricket analogy: UpdateAllViews() notifying every attached view after a data change is like an official scorer updating the central scoreboard system the instant a wicket falls, which then instantly refreshes the stadium screen, the TV graphic, and the app score simultaneously.
CView: Rendering and Interaction
A CView-derived class overrides OnDraw(CDC* pDC) to render the document's current state using the passed device context, and MFC calls OnDraw() both for normal screen repaints and, transparently, for print preview and actual printing, which is why OnDraw() should draw purely from document data rather than from any view-specific cached state. A view also typically overrides input handlers like OnLButtonDown() to let the user edit the document interactively, and it retrieves a pointer back to its owning document via GetDocument(), which is the standard way a view reads (and, through calling document methods, modifies) the data it's displaying.
Cricket analogy: OnDraw() being reused for both screen display and print preview is like a single official scorecard template being used identically whether it's projected on the stadium screen or printed as the match's official paper record - same layout logic, different output surface.
// CMyDoc.h
class CMyDoc : public CDocument
{
protected:
CStringArray m_items;
public:
virtual void Serialize(CArchive& ar) override
{
if (ar.IsStoring())
{
ar << (int)m_items.GetSize();
for (int i = 0; i < m_items.GetSize(); i++)
ar << m_items[i];
}
else
{
int count;
ar >> count;
m_items.RemoveAll();
for (int i = 0; i < count; i++)
{
CString s;
ar >> s;
m_items.Add(s);
}
}
}
void AddItem(const CString& s)
{
m_items.Add(s);
SetModifiedFlag();
UpdateAllViews(NULL);
}
};
// CMyView.cpp
void CMyView::OnDraw(CDC* pDC)
{
CMyDoc* pDoc = GetDocument();
int y = 10;
for (int i = 0; i < pDoc->GetItemCount(); i++)
{
pDC->TextOutW(10, y, pDoc->GetItem(i));
y += 20;
}
}SetModifiedFlag() marks the document as dirty, which is what powers the automatic 'Save changes before closing?' prompt - MFC checks this flag when the user tries to close a document or exit the app, so forgetting to call it after a data change means the framework won't realize there's unsaved work.
Document Templates
A CSingleDocTemplate (or CMultiDocTemplate for MDI applications) is the object, created once in CWinApp::InitInstance() and registered with AddDocTemplate(), that tells the framework which three classes - CDocument-derived, CFrameWnd-derived, and CView-derived - belong together for a given document type, along with the resource ID that supplies its menu, icon, and file-type string. When the user chooses File > New or File > Open, it is this template that MFC consults to instantiate the correct triplet of document, frame, and view objects and wire them together, which is why registering the wrong resource ID or class in a document template is a common source of a new document silently opening with the wrong menu or view.
Cricket analogy: A document template tying together CDocument, CFrameWnd, and CView classes is like a fixture list entry specifying which two teams, which stadium, and which broadcast crew are assigned together for a given match - one registration ties three components into a coherent event.
If you forget to call SetModifiedFlag() after mutating document data outside of a UI action that already calls it, MFC's dirty-tracking will not know the document changed, and the user can lose unsaved edits without ever seeing a save prompt when closing the app.
- Document/View separates an application's data (CDocument) from its on-screen presentation (CView).
- CDocument owns the data and typically overrides Serialize() to load and save it via a CArchive.
- UpdateAllViews() notifies every attached view to redraw after the document's data changes.
- CView overrides OnDraw() to render document state, reused for both screen and print preview.
- A view retrieves its owning document via GetDocument() to read and modify the underlying data.
- Document templates (CSingleDocTemplate/CMultiDocTemplate) register which document, frame, and view classes belong together.
- SetModifiedFlag() marks a document dirty, powering the automatic 'Save changes?' prompt on close.
Practice what you learned
1. What is the core purpose of the Document/View architecture in MFC?
2. Which CDocument member function is typically overridden to implement File > Open and File > Save?
3. What is the purpose of calling UpdateAllViews() on a document?
4. Why is CView::OnDraw() expected to render purely from document data rather than view-specific cached state?
5. What does a document template (such as CSingleDocTemplate) register with MFC?
Was this page helpful?
You May Also Like
MFC Application Architecture
How an MFC application is structured around CWinApp, message maps, and frame windows, and how these pieces cooperate to start up, route input, and shut down cleanly.
What Is MFC?
An introduction to the Microsoft Foundation Classes (MFC), the C++ framework that wraps the Win32 API into an object-oriented class library for building native Windows desktop applications.
MFC Project Structure
A tour of the files a Visual Studio MFC project generates - source, resource, and precompiled-header files - and how the build configuration ties them together.
Related Reading
Related Study Notes in Microsoft Technologies
Browse all study notesWindows 10 / UWP Development Study Notes
.NET · 30 topics
Microsoft TechnologiesWindows Batch Scripting Study Notes
Batch · 30 topics
Microsoft TechnologiesSilverlight Study Notes
.NET · 30 topics
Microsoft TechnologiesXAML Study Notes
.NET · 30 topics
Microsoft TechnologiesWPF (Windows Presentation Foundation) Study Notes
.NET · 30 topics
Microsoft TechnologiesMVVM Design Pattern Study Notes
.NET · 30 topics