「初始化載入預設文本,雙擊時切換至另一已知路徑文本」——核心在於正確關閉舊文檔、開啟新文檔、更新視圖,而非單純替換字串。
GetDocument()->SaveModified()GetDocument()->OnCloseDocument() 或 GetDocument()->DeleteContents()GetDocument()->OnOpenDocument(newPath)GetDocument()->UpdateAllViews(NULL)void CMyEditView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CString newPath = _T("D:\\Data\\AnotherText.txt"); // 目標路徑
CDocument* pDoc = GetDocument();
// 1. 若有未儲存修改,提示使用者
if (pDoc->IsModified()) {
int ret = AfxMessageBox(_T("當前文檔已修改,是否儲存?"), MB_YESNOCANCEL | MB_ICONQUESTION);
if (ret == IDYES) pDoc->DoFileSave();
else if (ret == IDCANCEL) return;
}
// 2. 關閉舊內容
pDoc->DeleteContents(); // 釋放舊文本緩衝區
// 3. 載入新檔案
if (!pDoc->OnOpenDocument(newPath)) {
AfxMessageBox(_T("無法開啟檔案:") + newPath);
// 可選:重新載入原預設檔案或建立空白文檔
pDoc->OnNewDocument();
return;
}
// 4. 通知所有視圖更新
pDoc->UpdateAllViews(NULL);
CEditView::OnLButtonDblClk(nFlags, point);
}
| 錯誤現象 | 原因 | 修正 |
|---|---|---|
| 顯示亂碼/空白 | 編碼不匹配(UTF-8 vs ANSI) | 覆寫 Serialize 指定 CStdioFile 開啟模式,或用 CFile::typeText | CFile::modeRead 讓 MFC 自動偵測 |
| 記憶體存取違規 | 未正確關閉舊文檔直接操作指標 | 嚴格遵循 DeleteContents → OnOpenDocument → UpdateAllViews 順序 |
| 標題列未更新 | 未呼叫 SetPathName | pDoc->SetPathName(newPath); 於 OnOpenDocument 成功後 |
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
CFile file;
if (!file.Open(lpszPathName, CFile::modeRead | CFile::shareDenyWrite))
return FALSE;
// 讀取前 4 字節判斷 BOM
BYTE bom[4];
file.Read(bom, 4);
file.SeekToBegin();
CString content;
if (bom[0]==0xEF && bom[1]==0xBB && bom[2]==0xBF) { // UTF-8 BOM
file.Seek(3, CFile::begin);
CStringA utf8; utf8.GetBufferSetLength(file.GetLength()-3);
file.Read(utf8.GetBuffer(), utf8.GetLength());
content = CA2W(utf8, CP_UTF8);
} else if (bom[0]==0xFF && bom[1]==0xFE) { // UTF-16 LE
// ... 類似處理
} else { // 預設 ANSI (系統代碼頁)
CStringA ansi; ansi.GetBufferSetLength(file.GetLength());
file.Read(ansi.GetBuffer(), ansi.GetLength());
content = CA2W(ansi, CP_ACP);
}
// 將 content 存入文檔內部緩衝區(視實作而定)
m_strText = content;
SetPathName(lpszPathName);
return TRUE;
}
MFC Document/View 架構下切換文本檔案,**關鍵在於文檔物件的正確重置與重新載入**,配合編碼處理與視圖通知,即可實現無縫切換。切勿嘗試直接操作 CEditCtrl::SetWindowText 繞過文檔層,否則會破壞撤銷/儲存/列印等核心功能。