利用 MFC 內建 `CRecentFileList` 類管理 MRU 列表,動態修改選單項,無需資源編輯器預置選單模板。
// MyApp.h
class CMyApp : public CWinApp {
public:
CRecentFileList* m_pRecentFileList;
// ...
};
// MyApp.cpp
BOOL CMyApp::InitInstance() {
// ... 標準初始化 ...
m_pRecentFileList = new CRecentFileList(
NULL, _T("Recent Files"), _T("File%d"), 4, ID_FILE_MRU_FILE1
);
m_pRecentFileList->ReadList(); // 從註冊表讀取
return TRUE;
}
void CMainFrame::OnFileOpen() {
CFileDialog dlg(TRUE);
if (dlg.DoModal() == IDOK) {
CString path = dlg.GetPathName();
if (OpenDocumentFile(path)) { // 或自定義打開邏輯
AfxGetApp()->m_pRecentFileList->Add(path);
UpdateRecentFilesMenu(); // 刷新選單顯示
}
}
}
void CMainFrame::UpdateRecentFilesMenu() {
CMenu* pMenu = GetMenu()->GetSubMenu(0); // 假設文件選單是第 0 個彈出選單
if (!pMenu) return;
// 1. 移除舊的最近檔案項 (從分隔符後到結束前)
// 簡化:記錄固定命令 ID 範圍 ID_FILE_MRU_FILE1 ~ ID_FILE_MRU_FILE4
for (UINT id = ID_FILE_MRU_FILE1; id <= ID_FILE_MRU_FILE4; ++id) {
pMenu->DeleteMenu(id, MF_BYCOMMAND);
}
// 2. 重新插入 (在「退出」項目前,假設退出命令 ID_EXIT)
CRecentFileList* pList = AfxGetApp()->m_pRecentFileList;
int count = pList->GetSize();
if (count > 0) {
pMenu->InsertMenu(ID_EXIT, MF_BYCOMMAND | MF_SEPARATOR, 0, _T("")); // 分隔符
for (int i = 0; i < count; ++i) {
CString name = pList->GetDisplayName(i, NULL);
if (!name.IsEmpty()) {
pMenu->InsertMenu(ID_EXIT, MF_BYCOMMAND | MF_STRING, ID_FILE_MRU_FILE1 + i, name);
}
}
}
}
// MainFrm.cpp 消息映射
BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWnd)
ON_COMMAND_RANGE(ID_FILE_MRU_FILE1, ID_FILE_MRU_FILE4, OnOpenRecentFile)
END_MESSAGE_MAP()
void CMainFrame::OnOpenRecentFile(UINT nID) {
int index = nID - ID_FILE_MRU_FILE1;
CString path = AfxGetApp()->m_pRecentFileList->GetDisplayName(index, NULL);
if (!path.IsEmpty()) {
OpenDocumentFile(path); // MFC 文檔/視圖架構自動處理
// 或對話框程式:PostMessage(WM_COMMAND, ID_FILE_OPEN); 並傳遞路徑
}
}