Multiple File Selection Dialog
Posted
by Zandro Arceo
on June 19th, 1999
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] = '\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)'\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++;
}
}

Comments
Easier Way to Select Multiple Files.
Posted by Legacy on 09/26/2003 12:00amOriginally posted by: Sergio A. Hernandez
-
ReplyWhy does it lose files if you change directories?
Posted by Mike Pliam on 01/27/2009 02:13pmYour code works nicely but if I change directories, it loses the files from any preceeding directories. Any way to fix that?
ReplyI agree this is not a good idea.....
Posted by Legacy on 03/05/2003 12:00amOriginally posted by: Richard 'vajuras' Osborne
I'm sorry but Borland is right. Why not just use OFN_ALLOWMULTISELECT? What codeguru needs is a tut on how to use CFileDialog.....
Reply
Why can not select only one file
Posted by Legacy on 01/19/2003 12:00amOriginally posted by: suvn.w
It works well but when I only select one file, it cann't work properly, why?
Replydude this seems pretty silly
Posted by Legacy on 02/21/2002 12:00amOriginally posted by: borland
you do know you can just call CFileDialog with parameters of OFN_ALLOWMULTISELECT, etc and it will let you pick more than one file. Inheriting a class on top of it is kinda silly don't you think?
ReplyLooking for the same
Posted by Legacy on 04/27/2001 12:00amOriginally posted by: Shrinivas
Thanks. I was looking for the same. thanks again - shrini
ReplyNot bad.
Posted by Legacy on 12/20/2000 12:00amOriginally posted by: Srinivasa
Its cool way of overridding CFileDialog behaviour.
ReplyThanX
Posted by Legacy on 05/17/2000 12:00amOriginally posted by: kabir
thanx for that, it solved a problem in less time than it would have taken
Replym_ofn.nMaxFile = 2048; // arbitrary limit?
Posted by Legacy on 01/11/2000 12:00amOriginally posted by: Malcolm Ross
Hi there,
I see that in your class you assign a buffer of 2048 characters for storing the list of filenames. Is 2048 just an arbitrarily chosen number, or did you choose 2048 for a special reason? I understand that for multiple filenames you'll need more characters than just _MAX_PATH, but is there a limit to how large a buffer you can assign?
Cheers,
Mal.
ReplyOverride OnFileOpen in CWinApp derived class.
Posted by Legacy on 06/19/1999 12:00amOriginally posted by: Gautam N. Lad
Reply