Multiple File Selection Dialog 

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++;

 }

}

History

Date Posted: June 19, 1999