, ,
This article was contributed by Zandro Arceo.
I wanted to open a number of files at the same time from a Visual C++/MFC ap
plication. 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 c
an 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 lpszFile
Name = NULL,
DWORD dwFlags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_ALLOWMULTISEL
ECT,
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 lpszFil
eName,
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] = '/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 selec
tion 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)'/0'; // next string please
strFilter += _T("*.*");
strFilter += (TCHAR)'/0'; // 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)'/0'; // next string please
filter += (TCHAR)'*';
filter += strFilterExt;
filter += (TCHAR)'/0'; // next string please
ofn.nMaxCustFilter++;
}
}