I wanted to open a number of files at the same time from a Visual C++/MFC application.
However, a ClassWizard generated
application (with file support) only allows for the opening of a single file at a time.
Therefore, I derived my own custom class from CFileDialog called MFileDlg. Using this class,
I can now specify multiple files to be opened from the Open File dialog.
Class Declaration:
class MFileDlg : public CFileDialog { DECLARE_DYNAMIC(MFileDlg) public: MFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt = NULL , LPCTSTR lpszFileName = NULL, DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISELECT, LPCTSTR lpszFilter = NULL, CWnd* pParentWnd = NULL) ; int DoModal(); virtual ~MFileDlg(); protected: //{{AFX_MSG(MFileDlg) // NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG TCHAR* m_pszFile; DECLARE_MESSAGE_MAP() };
Class Implementation:
IMPLEMENT_DYNAMIC(MFileDlg, CFileDialog) MFileDlg::MFileDlg(BOOL bOpenFileDialog, LPCTSTR lpszDefExt, LPCTSTR lpszFileName, DWORD dwFlags, LPCTSTR lpszFilter, CWnd* pParentWnd) : CFileDialog(bOpenFileDialog, lpszDefExt, lpszFileName, dwFlags, lpszFilter, pParentWnd) { m_pszFile = new TCHAR[2048]; //set a 2K buffer to hold selected files m_pszFile[0] = ' '; //initialize pointer; } BEGIN_MESSAGE_MAP(MFileDlg, CFileDialog) //{{AFX_MSG_MAP(MFileDlg) // NOTE - the ClassWizard will add and remove mapping macros here. //}}AFX_MSG_MAP END_MESSAGE_MAP() MFileDlg::~MFileDlg() { if (m_pszFile != NULL) delete [] m_pszFile; //cleanup } int MFileDlg::DoModal() { ASSERT_VALID(this); ASSERT(m_ofn.Flags & OFN_ALLOWMULTISELECT); //make sure multiple file selection is on m_ofn.lpstrFile = m_pszFile; //initialize the OPENFILENAME structure m_ofn.nMaxFile = 2048; return CFileDialog::DoModal(); }
How to Use:
1. On your CwinApp-derived class, override the OnOpenFile() function.
void CDigilogApp::OnFileOpen() { // TODO: Add your command handler code here MFileDlg dlgFile(TRUE); CString title, strFilter, strDefault; VERIFY(title.LoadString(AFX_IDS_OPENFILE)); // do for all doc template POSITION pos = GetFirstDocTemplatePosition(); BOOL bFirst = TRUE; while (pos != NULL) { CDocTemplate* pTemplate = GetNextDocTemplate(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)' '; // next string please strFilter += _T("*.*"); strFilter += (TCHAR)' '; // last string dlgFile.m_ofn.nMaxCustFilter++; dlgFile.m_ofn.lpstrFilter = strFilter; dlgFile.m_ofn.lpstrTitle = title; dlgFile.m_ofn.hwndOwner = AfxGetMainWnd()->GetSafeHwnd(); if (dlgFile.DoModal() == IDOK) { POSITION pos = dlgFile.GetStartPosition(); while (pos != NULL) { CString strPath = dlgFile.GetNextPathName(pos); if (strPath.Find(":\\") == 1 && strPath.GetLength() > 4) { // this means we have an invalid path that looks like this: // C:\cda.dgl // get rid of extra slash CString temp; temp = strPath.Left(3); temp += strPath.Mid(4); strPath = temp; } OpenDocumentFile(strPath); } } }
2. Add this declaration and function to your CwinApp- derived class .
static void AppendFilterSuffix(CString& filter, OPENFILENAME& ofn, CDocTemplate* pTemplate, CString* pstrDefaultExt); static void 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)' '; // next string please filter += (TCHAR)'*'; filter += strFilterExt; filter += (TCHAR)' '; // next string please ofn.nMaxCustFilter++; } }
History