MFC 應用程式啟動時,自動彈出一個對話框,列出多種文件類型供用戶選擇建立新文件,類似 Word 啟動時的「新建文件」選項。
MFC 文檔/視圖架構中,文件模板 (CDocTemplate) 定義了文件類型、框架視窗、視圖類別的關聯。當應用程式擁有 兩個或以上 的文件模板時,MFC 框架會自動在啟動時顯示「新建文件」對話框。
// 在 InitInstance() 中註冊多個文件模板
CSingleDocTemplate* pDocTemplate1;
pDocTemplate1 = new CSingleDocTemplate(
IDR_MAINFRAME, // 資源 ID
RUNTIME_CLASS(CMyDoc), // 文件類
RUNTIME_CLASS(CMainFrame), // 框架視窗類
RUNTIME_CLASS(CMyView) // 視圖類
);
AddDocTemplate(pDocTemplate1);
// 第二種文件類型
CSingleDocTemplate* pDocTemplate2;
pDocTemplate2 = new CSingleDocTemplate(
IDR_SECONDTYPE, // 不同的資源 ID
RUNTIME_CLASS(CSecondDoc),
RUNTIME_CLASS(CMainFrame),
RUNTIME_CLASS(CSecondView)
);
AddDocTemplate(pDocTemplate2);
// 每個文件類型需獨立的資源 ID
#define IDR_MAINFRAME 128
#define IDR_SECONDTYPE 129
// IDR_SECONDTYPE 對應的資源包含:
// - 選單資源
// - 工具列資源
// - 圖示資源
// - 文件類型描述字串
// 字串表中 IDR_SECONDTYPE 對應的字串 (用 '\n' 分隔)
/*
IDR_SECONDTYPE "第二類文件\n第二類文件\n第二類檔案 (*.sec)\n.sec\nSecondType.Document\nSecondType Document"
*/
// 格式:\n 分隔的 7 個部分:
// 1. 類型名稱 (選單顯示)
// 2. 類型名稱 (標題列)
// 3. 檔案過濾器描述
// 4. 副檔名
// 5. 註冊表 ProgID
// 6. 文件類型描述
// 7. (保留)
// CWinApp::OnFileNew() 簡化邏輯
void CWinApp::OnFileNew() {
if (m_pDocTemplates.GetCount() == 1) {
// 單一模板:直接建立預設文件
CDocTemplate* pTemplate = (CDocTemplate*)m_pDocTemplates.GetHead();
pTemplate->OpenDocumentFile(NULL);
} else {
// 多模板:顯示選擇對話框
CDocTemplate* pTemplate = GetDocTemplateForFileType();
if (pTemplate) {
pTemplate->OpenDocumentFile(NULL);
}
}
}
若需自訂對話框外觀或邏輯,可重寫 OnFileNew():
BOOL CMyApp::OnFileNew() {
// 自訂對話框類別
CNewFileDialog dlg(this);
if (dlg.DoModal() == IDOK) {
CDocTemplate* pTemplate = dlg.GetSelectedTemplate();
pTemplate->OpenDocumentFile(NULL);
return TRUE;
}
return FALSE; // 用戶取消
}
| 問題 | 原因 | 解決 |
|---|---|---|
| 啟動無選擇框 | 只有一個 DocTemplate | AddDocTemplate 至少兩個 |
| 選擇後無反應 | 資源 ID 衝突或類別未正確關聯 | 檢查 RUNTIME_CLASS 與資源 ID |
| 圖示不顯示 | 資源檔缺少圖示資源 | 為每個 IDR_* 添加圖示 |
| 副檔名關聯失效 | 字串表格式錯誤 | 嚴格遵循 7 段式格式 |
MFC 啟動時彈出文件類型選擇框,本質上是 多文件模板機制 的體現。只需在 InitInstance() 中註冊多個 CDocTemplate 衍生類實例,並配置對應的資源 ID 與字串表,框架即會自動處理選擇邏輯。這是 MFC 文檔/視圖架構支援多文件類型的標準做法。