首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> 關於VC++

MFC 文檔/視圖架構深度剖析:新建、開啟、儲存流程的核心追蹤與擴充點

     編輯:關於VC++

前言:為什麼要理解框架流程?

MFC 文檔/視圖架構封裝了大量常用功能 (新建、開啟、儲存),讓開發者專注業務邏輯。但這層「透明性」也帶來困擾:不知何時呼叫何種虛擬函式、欲修改預設行為卻無從下手。本文透過 Debug 追蹤,梳理多文檔 (MDI) 架構下三大核心流程,單文檔 (SDI) 僅將 CMultiDocTemplate 換為 CSingleDocTemplate 即可類推。

一、新建文檔流程 (ID_FILE_NEW)

ON_COMMAND(ID_FILE_NEW, CWinApp::OnFileNew)
入口: CWinApp::OnFileNew
  → CWinApp 預設實作呼叫: CDocManager::OnFileNew()
    1. 判斷是否有文檔模板,無則返回
    2. 多模板時彈出選擇對話框,取得模板指標
    3. 呼叫 CMultiDocTemplate::OpenDocumentFile()
      3.1 建立新文檔物件 (CDocument 派生)
      3.2 建立對應子框架 (CMDIChildWnd),建立 文檔-框架-視圖 關聯
      3.3 呼叫應用程式 OnNewDocument()
        a. CDocument::OnNewDocument() → DeleteContents()
        b. 使用者自訂初始化程式碼
      3.4 InitialUpdateFrame() 顯示視圖
      3.5 返回文檔指標
    4. 返回

關鍵擴充點

  • CDocument::OnNewDocument():初始化文檔資料結構
  • CDocument::DeleteContents():清理舊資料 (新建/開啟前皆呼叫)
  • CMultiDocTemplate::OpenDocumentFile():可覆寫自訂文檔建立邏輯

二、開啟文檔流程 (ID_FILE_OPEN)

ON_COMMAND(ID_FILE_OPEN, CWinApp::OnFileOpen)
入口: CWinApp::OnFileOpen
  → CDocManager::OnFileOpen()
    1. 彈出檔案對話框,取得完整路徑
    2. 呼叫應用程式 OpenDocumentFile(lpszFileName)
      2.1 使用者程式碼
      2.2 CWinApp::OpenDocumentFile() → CDocManager::OpenDocumentFile()
        a. 檢查檔案是否已開啟,是則激活視窗返回
        b. CMultiDocTemplate::OpenDocumentFile()
          b.1 建立文檔、子框架
          b.2 呼叫應用程式 OnOpenDocument()
            (1) CDocument::OnOpenDocument()
              . 開啟檔案物件 (CFile)
              . DeleteContents()
              . 建立 CArchive 關聯檔案
              . 呼叫文檔 Serialize() 反序列化
              . 關閉 CArchive、檔案
            (2) 顯示檔案視窗
          b.3 返回
    3. 返回

關鍵擴充點

  • CDocument::OnOpenDocument():預設實作序列化,可覆寫自訂檔案格式 (XML/JSON/資料庫)
  • CDocument::Serialize():核心資料持久化邏輯,ar.IsStoring() 區分讀/寫
  • CDocManager::OpenDocumentFile():可攔截重複開啟、唯讀處理

三、儲存文檔流程 (ID_FILE_SAVE / SAVE_AS)

儲存 (ID_FILE_SAVE): ON_COMMAND(ID_FILE_SAVE, CDocument::OnFileSave)
  入口: CDocument::OnFileSave()
    → CDocument::DoFileSave()
      若檔名為空或唯讀 → DoSave(NULL)
      否則 → DoSave(m_strPathName)

另存新檔 (ID_FILE_SAVE_AS): ON_COMMAND(ID_FILE_SAVE_AS, CDocument::OnFileSaveAs)
  入口: CDocument::OnFileSaveAs()
    → DoSave(NULL)

CDocument::DoSave(lpszPathName, bReplace)
  若 lpszPathName 為 NULL:
    1. 設定預設檔名
    2. 彈出儲存對話框取得檔名
  3. 呼叫應用程式 OnSaveDocument()
    3.1 使用者程式碼
    3.2 CDocument::OnSaveDocument()
      a. 建立/開啟檔案
      b. 建立 CArchive
      c. 呼叫 Serialize() 序列化
      d. 關閉檔案、CArchive
      e. 設定「未修改」旗標
  4. 返回

關鍵擴充點

  • CDocument::OnSaveDocument():可覆寫加入加密、壓縮、版本控制
  • CDocument::DoSave():控制對話框行為、預設路徑、副檔名過濾
  • CDocument::SetModifiedFlag():標記髒資料,提示儲存

四、實用除錯技巧

  1. 在 ClassWizard 加入上述虛擬函式,設中斷點
  2. Debug → 單步追蹤 (F11),觀察呼叫堆疊
  3. 跳過 MFC 核心原始碼 (無符號資訊)
  4. 同法可追蹤 MFC 範例程式 (如 SCRIBBLE)

五、架構圖解:核心類別關係

CWinApp
  └─ CDocManager
       └─ CMultiDocTemplate / CSingleDocTemplate
            ├─ CreateNewDocument() → CDocument
            ├─ CreateNewFrame()    → CMDIChildWnd / CFrameWnd
            ├─ InitialUpdateFrame() → CView
            └─ OpenDocumentFile()  → 統籌上述流程

結語

掌握這三大流程的呼叫鏈與虛擬函式擴充點,即可:

  • 自訂檔案格式 (覆寫 Serialize)
  • 實作自動儲存/版本備份 (覆寫 OnSaveDocument)
  • 控制多文檔行為 (覆寫 OpenDocumentFile)
  • 整合資料庫/雲端儲存 (重寫 OnOpenDocument/OnSaveDocument)

建議開發者親自追蹤一次,建立心智模型,事半功倍。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved