Understanding MFC Application Control Flow: A Deep Dive into SDI, MDI, and Dialog Applications
MFC - SDI, MDI, and Dialog Applications
Introduction
Microsoft Foundation Classes (MFC) remains a crucial framework for Windows desktop development, particularly in enterprise applications. In this deep dive, we'll explore the three fundamental MFC application architectures: Single Document Interface (SDI), Multiple Document Interface (MDI), and Dialog-based applications. We'll examine their control flows, object creation sequences, and practical implementations.
The Three Pillars of MFC Applications
1. Single Document Interface (SDI)
SDI applications are like a one-track mind – they handle a single document at a time. Think of applications like Notepad, where you work with one file in one window.
Key characteristics:
One document active at a time
Simple window hierarchy
Direct frame-to-view relationship
Lightweight memory footprint
When to use SDI:
Simple document editing tasks
Single-focus applications
Tools that process one file at a time
Applications requiring minimal window management
2. Multiple Document Interface (MDI)
MDI applications are the multitaskers of the Windows world. Think Microsoft Excel or Word, where multiple documents live within a parent window.
Key characteristics:
Multiple active documents
Parent-child window hierarchy
Complex window management
Shared resource framework
When to use MDI:
Complex document management systems
Applications requiring document comparison
Tools with multiple concurrent workflows
Enterprise-level software suites
3. Dialog-Based Applications
The simplest of the three, dialog-based applications are perfect for task-focused tools and utilities.
Key characteristics:
No document-view architecture
Form-centric interface
Simplified message handling
Focus on user input
When to use Dialog-based:
Configuration utilities
Simple data entry forms
Quick tools and utilities
Wizard-style applications
Deep Dive: Control Flow Patterns
SDI Control Flow
// 1. SDI Application Core Classes
class CMyApp : public CWinApp {
public:
BOOL InitInstance() {
// Register document template
CSingleDocTemplate* pDocTemplate = new CSingleDocTemplate(
IDR_MAINFRAME,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// Create main frame window
CMainFrame* pFrame = new CMainFrame;
if (!pFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;
m_pMainWnd = pFrame;
pFrame->ShowWindow(SW_SHOW);
pFrame->UpdateWindow();
return TRUE;
}
};
class CMainFrame : public CFrameWnd {
DECLARE_DYNCREATE(CMainFrame)
protected:
BOOL PreCreateWindow(CREATESTRUCT& cs) {
return CFrameWnd::PreCreateWindow(cs);
}
// Message map and handlers
DECLARE_MESSAGE_MAP()
};
class CMyDoc : public CDocument {
DECLARE_DYNCREATE(CMyDoc)
protected:
BOOL OnNewDocument() {
if (!CDocument::OnNewDocument())
return FALSE;
return TRUE;
}
// Document serialization and data members
};
class CMyView : public CView {
DECLARE_DYNCREATE(CMyView)
protected:
void OnDraw(CDC* pDC) {
CMyDoc* pDoc = GetDocument();
// Drawing code
}
// View message handlers
};
// 2. MDI Application Core Classes
class CMyMDIApp : public CWinApp {
public:
BOOL InitInstance() {
// Register document template
CMultiDocTemplate* pDocTemplate = new CMultiDocTemplate(
IDR_MYTYPE,
RUNTIME_CLASS(CMyDoc),
RUNTIME_CLASS(CMyChildFrame),
RUNTIME_CLASS(CMyView));
AddDocTemplate(pDocTemplate);
// Create main MDI Frame window
CMainMDIFrame* pMainFrame = new CMainMDIFrame;
if (!pMainFrame->LoadFrame(IDR_MAINFRAME)) return FALSE;
m_pMainWnd = pMainFrame;
pMainFrame->ShowWindow(SW_SHOW);
pMainFrame->UpdateWindow();
return TRUE;
}
};
class CMainMDIFrame : public CMDIFrameWnd {
DECLARE_DYNCREATE(CMainMDIFrame)
protected:
BOOL PreCreateWindow(CREATESTRUCT& cs) {
return CMDIFrameWnd::PreCreateWindow(cs);
}
};
class CMyChildFrame : public CMDIChildWnd {
DECLARE_DYNCREATE(CMyChildFrame)
protected:
BOOL PreCreateWindow(CREATESTRUCT& cs) {
return CMDIChildWnd::PreCreateWindow(cs);
}
};
// 3. Dialog-Based Application Core Classes
class CMyDialogApp : public CWinApp {
public:
BOOL InitInstance() {
CMyDialog dlg;
m_pMainWnd = &dlg;
INT_PTR nResponse = dlg.DoModal();
return FALSE;
}
};
class CMyDialog : public CDialog {
public:
CMyDialog() : CDialog(IDD_DIALOG) {}
protected:
virtual BOOL OnInitDialog() {
CDialog::OnInitDialog();
// Initialize controls
return TRUE;
}
// Message handlers
DECLARE_MESSAGE_MAP()
};
The SDI flow is straightforward:
Application initialization
Single frame window creation
Document template registration
View creation and attachment
Message loop processing
MDI Control Flow
MDI adds complexity with its parent-child relationship:
Main frame initialization
Child window template registration
Document-view pair creation per child
Synchronized message handling
Dialog Control Flow
Dialog applications simplify the flow:
Dialog resource loading
Control initialization
Event handler setup
Modal/modeless loop management
Object Creation Sequence: A Closer Look
SDI Creation Sequence
CWinApp
derived class instantiationDocument template registration
Frame window creation
View attachment
Document binding
MDI Creation Sequence
Main frame initialization
Client window creation
Child frame management setup
Document-view pair generation
Window hierarchy establishment
Best Practices and Common Pitfalls
Do's:
Use proper message maps for event handling
Implement clean document-view separation
Handle window destruction properly
Manage resources effectively
Don'ts:
Mix architecture patterns
Ignore memory management
Bypass MFC's document-view architecture
Neglect error handling
Performance Considerations
Memory Management
SDI: Lightweight, single instance
MDI: Higher memory overhead
Dialog: Minimal resource usage
Processing Overhead
SDI: Efficient message routing
MDI: Complex window management
Dialog: Direct message handling
Conclusion
Choosing the right MFC architecture depends on your application's needs:
SDI for focused, single-document applications
MDI for complex document management
Dialog-based for simple utilities and forms
Understanding these patterns helps build more maintainable and efficient Windows applications. The key is matching the architecture to your use case while following MFC best practices.
Next week: We'll explore advanced MFC topics including custom controls, document serialization, and modern UI integration. Subscribe to stay updated!