Introduction
This code snippet will show you how to select multiple files and folders by adding a custom dialog box to your project. There are built-in controls in MFC to select a folder (SHBrowseForFolder
) or a file (CFileDialog
), but you cannot select multiple folders or files using these controls. Here, I am giving you a dialog box; you can call it from your application, and can select multiple files and folders at a time.
This article will also give you an idea about:
- How to edit your resource (.rc and Resource.h) file
- How to extract the system icon list
- How to traverse through the folder structure of Windows
How to use the code
Here, you have to do a little job. It is an MFC application and uses a dialog, so you have to manually edit your .rc and Resource.h files, and also your App class. So, let's start to use the code..
- Copy the BrowseDlg.h and BrowseDlg.cpp files to your project folder.
- Change the project header file of BrowseDlg.cpp from
#include "BrowseForFiles.h"
to your project header file.
- Change the name of the App class that is used in the BrowseDlg.cpp from
extern CBrowseForFilesApp theApp;
to your App class. Repeat it wherever it occurs.
- Open your project header file, and add the following lines as public members:
CImageList m_ImgList;
CList<CString,CString&> MainDirList;
- Then, open your project .cpp file and add the following lines to
InitInstance()
before beginning the execution of your code:
HIMAGELIST hSystemSmallImageList;
SHFILEINFO ssfi;
hSystemSmallImageList =
(HIMAGELIST)SHGetFileInfo(
(LPCTSTR)_T("c:\\"),
0,
&ssfi,
sizeof(SHFILEINFO),
SHGFI_SYSICONINDEX | SHGFI_SMALLICON);
m_ImgList.Attach(hSystemSmallImageList);
- Then, open your Resource.h file and take care while editing. Add the following lines to the list of
#define
s:
#define IDD_BROWSE 129
#define IDC_PATH 1002
#define IDC_DRIVE 1003
#define IDC_FILES 1004
#define IDC_UP 1005
Here, you must take care to avoid duplication of constants. For example, if 129 or 1003 or any of the above numbers already exists, then you must modify the numbers to a new one that is not allocated by any other controls. Here, the best idea is to find the highest three digit number from your file and give it to IDD_BROWSE
. And find the highest four digit number and assign it to IDC_PATH
, and assign the numbers to the above controls with an increment of one. For example, if 1023 is the highest number assigned to controls, then modify the above values as follows:
#define IDC_PATH 1024
#define IDC_DRIVE 1025
#define IDC_FILES 1026
#define IDC_UP 1027
So you have added controls to the Resource file. Now, modify the APISTUDIO
defined constants also, as follows:
Give the highest three digit value plus one (+1) to the following variable:
#define _APS_NEXT_RESOURCE_VALUE 130
Give the highest four digit value plus one (+1) to the following variable:
#define _APS_NEXT_CONTROL_VALUE 1028
These variables are used by APISTUDIO
when you add new controls to the project.
- Then, open your .rc file in text mode and add the following code to the Dialog section:
IDD_BROWSE DIALOG DISCARDABLE 0, 0, 212, 214
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Add Files and Folders"
FONT 8, "MS Sans Serif"
BEGIN
DEFPUSHBUTTON "OK",IDOK,112,188,50,14
PUSHBUTTON "Cancel",IDCANCEL,48,187,50,14
EDITTEXT IDC_PATH,7,165,200,16,
ES_AUTOHSCROLL | ES_READONLY
COMBOBOX IDC_DRIVE,76,13,29,125,
CBS_DROPDOWN | CBS_SORT |
WS_VSCROLL | WS_TABSTOP
CONTROL "List1",IDC_FILES,"SysListView32",
LVS_REPORT | WS_BORDER |
WS_TABSTOP,7,29,200,122
LTEXT "Drive",IDC_STATIC,51,16,18,8
LTEXT "Path",IDC_STATIC,7,155,16,8
PUSHBUTTON "UP",IDC_UP,114,13,20,14
END
And also add the following code to the DESIGNINFO
section:
IDD_BROWSE, DIALOG
BEGIN
LEFTMARGIN, 7
TOPMARGIN, 7
BOTTOMMARGIN, 207
END
So the BrowseDlg
is ready to use. Call the dialog wherever you want as follows:
CBrowseDlg dlgBrowse;
dlgBrowse.DoModal();
After completing execution of the dialog, you will get the selected list of files in the app variable named MainDirList
. You can retrive the contents of the CList
as follows:
POSITION position;
extern CTestBrwsApp theApp;
int iCnt = theApp.MainDirList.GetCount();
position = theApp.MainDirList.GetHeadPosition();
for(i = 0; i < iCnt; i++ )
{
m_SelectedList.AddString((CString)
theApp.MainDirList.GetNext(position));
}
So we completed the job. If you have any doubts, please refer to the sample project provided with this article.