MFC 多文件中同時開啟多個文件
阿新 • • 發佈:2019-01-03
MFC多文件中的開啟繼承自CWinAppEx中的函式OnFileOpen(),這一點在CXXX.cpp中可以看到。比如如下:
// CCVMFCApp BEGIN_MESSAGE_MAP(CCVMFCApp, CWinAppEx) ON_COMMAND(ID_APP_ABOUT, &CCVMFCApp::OnAppAbout) // 基於檔案的標準文件命令 ON_COMMAND(ID_FILE_NEW, &CWinAppEx::OnFileNew) ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen) // 標準列印設定命令 ON_COMMAND(ID_FILE_PRINT_SETUP, &CWinAppEx::OnFilePrintSetup) END_MESSAGE_MAP()
中的ON_COMMAND(ID_FILE_OPEN, &CWinAppEx::OnFileOpen)
它預設的只能開啟一個文件,那如果想開啟多個文件腫麼辦呢?
這裡給一個輔助類MutiOpenDocManager,程式碼如下:
MutiOpenDocManager.h:
// MutiOpenDocManager.h: interface for the CMutiOpenDocManager class. // ////////////////////////////////////////////////////////////////////// #if !defined(AFX_MUTIOPENDOCMANAGER_H__8E7F5957_C207_4C9E_BA92_979203C32025__INCLUDED_) #define AFX_MUTIOPENDOCMANAGER_H__8E7F5957_C207_4C9E_BA92_979203C32025__INCLUDED_ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 class CMutiOpenDocManager : public CDocManager { public: virtual BOOL DoPromptFileNames(CStringList& fileNames,UINT nIDSTitle,DWORD lFlags,BOOL bOpenFileDialog,CDocTemplate* pTemplate); virtual void OnFileOpen(); CMutiOpenDocManager(); virtual ~CMutiOpenDocManager(); void AppendFilterSuffix(CString &filter, OPENFILENAME &ofn, CDocTemplate *pTemplate, CString *pstrDefaultExt); }; #endif // !defined(AFX_MUTIOPENDOCMANAGER_H__8E7F5957_C207_4C9E_BA92_979203C32025__INCLUDED_)
MutiOpenDocManager.cpp:
// MutiOpenDocManager.cpp: implementation of the CMutiOpenDocManager class. // ////////////////////////////////////////////////////////////////////// #include "stdafx.h" #include "MutiOpenDocManager.h" #ifdef _DEBUG #undef THIS_FILE static char THIS_FILE[]=__FILE__; #define new DEBUG_NEW #endif ////////////////////////////////////////////////////////////////////// // Construction/Destruction ////////////////////////////////////////////////////////////////////// CMutiOpenDocManager::CMutiOpenDocManager() { } CMutiOpenDocManager::~CMutiOpenDocManager() { } void CMutiOpenDocManager::OnFileOpen() { CStringList newNames; if(!DoPromptFileNames(newNames,AFX_IDS_OPENFILE,OFN_HIDEREADONLY|OFN_FILEMUSTEXIST|OFN_ALLOWMULTISELECT,TRUE,NULL)) return; POSITION pos=newNames.GetHeadPosition(); while(pos) { CString newName=newNames.GetNext(pos); AfxGetApp()->OpenDocumentFile(newName); } } BOOL CMutiOpenDocManager::DoPromptFileNames(CStringList& fileNames, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate *pTemplate) { CFileDialog dlgFile(bOpenFileDialog); CString title; VERIFY(title.LoadString(nIDSTitle)); dlgFile.m_ofn.Flags |= lFlags; CString strFilter; CString strDefault; if (pTemplate != NULL) { ASSERT_VALID(pTemplate); AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault); } else { // do for all doc template POSITION pos = m_templateList.GetHeadPosition(); BOOL bFirst = TRUE; while (pos != NULL) { CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos); AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, bFirst ? &strDefault : NULL); bFirst = FALSE; } } // append the "*.*" all files filter CString allFilter; VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER)); strFilter += allFilter; strFilter += (TCHAR)'\0'; // next string please #ifndef _MAC strFilter += _T("*.*"); #else strFilter += _T("****"); #endif strFilter += (TCHAR)'\0'; // last string dlgFile.m_ofn.nMaxCustFilter++; dlgFile.m_ofn.lpstrFilter = strFilter; #ifndef _MAC dlgFile.m_ofn.lpstrTitle = title; #else dlgFile.m_ofn.lpstrPrompt = title; #endif CString strFileNames; dlgFile.m_ofn.lpstrFile=strFileNames.GetBuffer(2048); dlgFile.m_ofn.nMaxFile=2048; BOOL bResult=dlgFile.DoModal()==IDOK?TRUE:FALSE; strFileNames.ReleaseBuffer(); if(!bResult) return FALSE;//取消開啟檔案操作 //將檔名拷貝到一個字串列表中 POSITION pos=dlgFile.GetStartPosition(); while(pos) { fileNames.AddTail(dlgFile.GetNextPathName(pos)); } return TRUE; } //下面的函式是DoPromptFileNames函式中需要呼叫的模組函式 void CMutiOpenDocManager::AppendFilterSuffix(CString &filter, OPENFILENAME &ofn, CDocTemplate *pTemplate, CString *pstrDefaultExt) { ASSERT_VALID(pTemplate); ASSERT_KINDOF(CDocTemplate, pTemplate); CString strFilterExt, strFilterName; if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) && !strFilterExt.IsEmpty() && pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) && !strFilterName.IsEmpty()) { // a file based document template - add to filter list ASSERT(strFilterExt[0] == '.'); if (pstrDefaultExt != NULL) { // set the default extension *pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1; // skip the '.' ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt); ofn.nFilterIndex = ofn.nMaxCustFilter + 1; // 1 based number } // add to filter filter += strFilterName; ASSERT(!filter.IsEmpty()); // must have a file type name filter += (TCHAR)'\0'; // next string please filter += (TCHAR)'*'; filter += strFilterExt; filter += (TCHAR)'\0'; // next string please ofn.nMaxCustFilter++; } }
然後再在CXXX.cpp的一個位置插入一句話!至關重要:
BOOL CCVMFCApp::InitInstance()
{
// 如果一個執行在 Windows XP 上的應用程式清單指定要
// 使用 ComCtl32.dll 版本 6 或更高版本來啟用視覺化方式,
//則需要 InitCommonControlsEx()。否則,將無法建立視窗。
INITCOMMONCONTROLSEX InitCtrls;
InitCtrls.dwSize = sizeof(InitCtrls);
// 將它設定為包括所有要在應用程式中使用的
// 公共控制元件類。
InitCtrls.dwICC = ICC_WIN95_CLASSES;
InitCommonControlsEx(&InitCtrls);
CWinAppEx::InitInstance();
// 初始化 OLE 庫
if (!AfxOleInit())
{
AfxMessageBox(IDP_OLE_INIT_FAILED);
return FALSE;
}
AfxEnableControlContainer();
// 標準初始化
// 如果未使用這些功能並希望減小
// 最終可執行檔案的大小,則應移除下列
// 不需要的特定初始化例程
// 更改用於儲存設定的登錄檔項
// TODO: 應適當修改該字串,
// 例如修改為公司或組織名
SetRegistryKey(_T("應用程式嚮導生成的本地應用程式"));
LoadStdProfileSettings(4); // 載入標準 INI 檔案選項(包括 MRU)
InitContextMenuManager();
InitKeyboardManager();
InitTooltipManager();
CMFCToolTipInfo ttParams;
ttParams.m_bVislManagerTheme = TRUE;
theApp.GetTooltipManager()->SetTooltipParams(AFX_TOOLTIP_TYPE_ALL,
RUNTIME_CLASS(CMFCToolTipCtrl), &ttParams);
// 註冊應用程式的文件模板。文件模板
// 將用作文件、框架視窗和檢視之間的連線
CMultiDocTemplate* pDocTemplate;
m_pDocManager = new CMutiOpenDocManager;//注意必須在此位置新增此句
pDocTemplate = new CMultiDocTemplate(IDR_CVMFCTYPE,
RUNTIME_CLASS(CCVMFCDoc),
RUNTIME_CLASS(CChildFrame), // 自定義 MDI 子框架
RUNTIME_CLASS(CCVMFCView));
if (!pDocTemplate)
return FALSE;
AddDocTemplate(pDocTemplate);
// 建立主 MDI 框架視窗
CMainFrame* pMainFrame = new CMainFrame;
if (!pMainFrame || !pMainFrame->LoadFrame(IDR_MAINFRAME))
{
delete pMainFrame;
return FALSE;
}
m_pMainWnd = pMainFrame;
// 僅當具有後綴時才呼叫 DragAcceptFiles
// 在 MDI 應用程式中,這應在設定 m_pMainWnd 之後立即發生
// 分析標準外殼命令、DDE、開啟檔案操作的命令列
CCommandLineInfo cmdInfo;
ParseCommandLine(cmdInfo);
// 排程在命令列中指定的命令。如果
// 用 /RegServer、/Register、/Unregserver 或 /Unregister 啟動應用程式,則返回 FALSE。
if (!ProcessShellCommand(cmdInfo))
return FALSE;
// 主視窗已初始化,因此顯示它並對其進行更新
pMainFrame->ShowWindow(m_nCmdShow);
pMainFrame->UpdateWindow();
return TRUE;
}
注意45行的那句話,這是因為在建立類例項的時候將文件類定義為MutiOpenDocManager類,就可以使用其中的開啟函數了。
當然,如果工程是對話方塊就更好辦了,直接把onopen函式寫成這樣即可開啟多個文件:
void CCFileDialogST_demoDlg::OnOpen()
{
CFileDialogST dlg(TRUE, NULL, NULL, /*OFN_HIDEREADONLY | */OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, _T("All files\0*.*\0"), this);
CString sPathName;
int nRetValue;
nRetValue = dlg.DoModal();
if (nRetValue == IDOK)
{
POSITION Pos;
Pos = dlg.GetStartPosition();
while (Pos != NULL)
{
sPathName = dlg.GetNextPathName(Pos);
MessageBox(sPathName, _T("GetNextPathName"), MB_ICONINFORMATION);
}
} // if
} // End of OnOpen