Click here to Skip to main content
Click here to Skip to main content

File tree control allowing selection of multiple files and folders

By , 4 Jun 2007
 

Sample Image - FileTreeCtrl.jpg

Introduction

The provided CFileTreeCtrl is the MFC tree control, showing files in a manner similar to the left-hand side of Windows Explorer. Contrary to Windows Explorer, however, it allows the selection of multiple files and folders for further processing in your program. You can do this using the check boxes to the left of every file and folder. When selecting a folder, you can specify whether to include or not include the files from the subfolders. At any time, you can request that the control give you the lists of selected files and folders. You can also get information on how many files are selected in any folder.

States of check boxes

The following states of check boxes are supported:

check03 the folder does not contain any files
check01 the folder or file is not selected
check02 the file is selected
check04 all the files from the folder are selected, including the files of some subfolders
check05 all the files from the folder are selected, including the files from all subfolders
check06 all the files from the folder are selected, excluding the files from all subfolders
check07 some files in the folder are selected, files from subfolders are not
check08 some files in the folder are selected, as well as from all subfolders
check09 some files in the folder are selected, as well as from some subfolders
check10 the files from all subfolders are selected, but no files in the folder itself
check11 the files from some subfolders are selected, but no files in the folder itself

You can toggle through the states of check boxes, clicking on the item with a mouse.

Implementation of CFileTreeCtrl

  • Add the standard Tree Control to your dialog box or form view. Make sure it has check boxes style enabled. Use the More Styles tab in Tree Control properties.
    Tree Control properties
  • Add a new bitmap resource into your project and name it IDB_STATE. The BMP file for this resource is included with the source files. It includes 16 images for different states of check boxes. 5 of them are empty, though.
  • Then you can derive a new class from CFileTreeCtrl if you don't want to include all of the files into the control, but only the files of a specific type. To do this, in your derived class you need to override the virtual function MatchExtension. See below for details.
  • After this, you need to use the Class Wizard to add a member variable for the Tree Control resource to your dialog class. Then go to the header file for the dialog and change the type of this variable in the AFX_DATA section from CTreeCtrl to the name of your CFileTreeCtrl derived class.

CFileTreeCtrl class members

Here, I will describe only the public members of CFileTreeCtrl and the virtual function MatchExtension. The function of others you can guess from the source code.

BOOL DisplayTree()

Call this function to fill your file tree control with files. Usually, it is done in OnInitDialog() or in OnInitialUpdate(). The function returns true, if successful.

void AddHidFolder(int nFolder, CString strPath="")

Call this function before calling DisplayTree() to tell the control not to display certain folders. You can specify either the CSIDL identifier of the special folder (using nFolder), or the full path to the folder (using strPath; in this case, nFolder should be 0). Usually, you don't want to show the Recycle Bin and the Control Panel. So, add these lines to your program before calling DisplayTree():

 // m_FileTree is the member variable for the Tree Control
 m_FileTree.AddHidFolder(CSIDL_BITBUCKET); 
 m_FileTree.AddHidFolder(CSIDL_CONTROLS);

CString GetInfo(HTREEITEM hItem)

Gets the string of information on how many files and folders are selected in the folder. This is indicated by hItem, the handle to the item of Tree Control. The string is returned in this format: "Files: 15; Dirs: 22; SelFiles: 0; SelDirs: 0; PartDirs: 3", where Files is the total number of files in a folder, Dirs is the total number of subfolders, SelFiles is the number of selected files, SelDirs is the number of fully selected subfolders and PartDirs is the number of partially selected subfolders. If the item is a file or folder that has not been expanded yet, all the elements are -1. For example, to get the info on the currently selected folder, you can use:

m_strText = m_FileTree.GetInfo(m_FileTree.GetSelectedItem());

int GetSelectedFiles(CString* &SelFiles)

Returns the number of the selected files. The SelFiles parameter points to the array of strings containing the full names of all selected files. The memory for the array is allocated inside the GetSelectedFiles, but you need to delete it yourself using delete[] SelFiles.

int GetSelectedFolders(CString* &SelFolders)

Returns the number of the selected folders that have not been expanded yet. The SelFolders parameter points to the array of strings containing the full names of the selected folders without the closing "\". The first character of the returned strings indicate the type of the selection: "f" means only files within the folder (check06), "F" means only subfolders (check10) and "A" means all the files and all the subfolders (check05). The memory for the array is allocated inside GetSelectedFolders, but you need to delete it yourself using delete[] SelFolders.

CString GetSelectedFile()

Returns the string containing the full name of the currently selected item in the File Tree Control.

virtual bool MatchExtension(CString file)

Override this virtual function in your CFileTreeCtrl derived class in case you don't want to include all the files into the control, but only the files of a specific type. The function gets the name of the file; it should return true if the file should be included and false otherwise. For example, if you want to show only EXE files, do the following:

bool CMyFileTreeCtrl::MatchExtension(CString file)
{
  CString strTemp = file.Right(4);
  if (!strTemp.CollateNoCase(".EXE")) return TRUE;
  return FALSE;
}

If you do not want to show files at all, but only folders, override the function as follows:

bool CMyFileTreeCtrl::MatchExtension(CString file)
{
   return FALSE;
}

Acknowledgement

I would like to thank Johnson Zhou and PJ Naughter. I used some portions of their code in my class. I have also used one of the samples in MSDN and took the major portions of code from there, but now, unfortunately, I do not remember exactly which sample I used. I could have probably used the code of some other members of CodeProject, too. If you see your code in my source, tell me and I will include you in the Acknowledgement section. Thanks to all the members and the staff of the Code Project! You are all doing the wonderful job of making programming fun!

History

  • 19 January, 2006 -- Original version posted
  • 4 June, 2007 -- Article edited and posted to the main CodeProject.com article base

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Victor Ricklefs
Kazakstan Kazakstan
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
GeneralMy vote of 1memberstaffan_v12 Oct '12 - 2:31 
When I try to compile the demo project I get no less than 306 errors and 15 warnings.
GeneralRe: My vote of 1memberVictor Ricklefs12 Oct '12 - 8:19 
Look at the year of publication. It was developed for Visual C++ 6.0. No gurantee it will work for Visual Studio 2012
QuestionSee files created after the applications is startedmembererau7111 Jun '12 - 10:11 
Is it possible to see a file created after the application is started or we see in the tree only the files created before the application is started?
 
regards,
QuestionUnable to get selected folder list when selecting a sub folder first and then its parent foldermemberamaCoder9 Jan '12 - 7:33 
Hi,
I am to Unable to get the correct selected folder list when i select a sub folder first and then select its parent folder. When i do this the list only shows the sub folder path but not the parent folder path. How can i edit the code in such a way that if i select a folder and its sub folder i should get the path to both the parent folder and its sub folder in the selected folders list.
Generalgoodmember09dzxue5 Mar '11 - 5:31 
well done
GeneralMy vote of 5memberleechoohyoung12 Jan '11 - 18:47 
good job!
GeneralMy vote of 5memberMember 14304118 Oct '10 - 20:15 
excellent example. Adopted in my code.
GeneralCan't hide control panel in the Window7 & vistamemberxw32784 Jan '10 - 20:48 
hi,I had a try~~
this project can't hide control panel in windows7 & vista
could you explain for this problem????
thank you very much~~
GeneralRe: Can't hide control panel in the Window7 & vistamemberVictor Ricklefs5 Jan '10 - 4:32 
Sorry, the project was developed several years ago when Vista and Windows 7 did not exist. It has special function (or if statement, I don't remember already) which hides such elements as control panel, desktop, printers, etc. I guess control panel is named smth. different in Vista than it used to be in XP. Maybe some kind of SDK or googling will help...
Generalthank you very muchmembera1188826 May '09 - 22:33 
i have not see about the code,but thank you first!
GeneralThank you!memberlzd200216835 Dec '08 - 16:39 
Hi! Thank you very much! Very good! Smile | :)
 
lzd

GeneralWhen Running FileTreeDialogmemberMember 287643917 Sep '08 - 9:53 
When I execute the apllication and close it, the process still running even with the window closed, and only I can stop it with CTRL ALT DEL. May be my fault.
Thanks
GeneralRe: When Running FileTreeDialogmemberVictor Ricklefs17 Sep '08 - 22:52 
Stange, it usually does not behave this way. At least in situation when I tested it. Can you be more descriptive on what is exactly happening?
GeneralRe: When Running FileTreeDialogmemberMember 287643918 Sep '08 - 1:09 
First of all Thanks for your help.
My problem is: When I execute your application on the Microsoft Visual C++ and next close the application (clicking on Ok or Close button) the appearance is closed, but if I rebuild all next, the message from compiler is:
 
Generating Code...
Linking...
LINK : fatal error LNK1104: cannot open file "Release/FileTreeDialog.exe"
Error executing link.exe.
 
FileTreeDialog.exe - 1 error(s), 0 warning(s)
 
Solution is CTRL ALT DEL because the programm still running.
 
I don´t know if is my fault.
Thanks Victor Ricklefs.
GeneralRe: When Running FileTreeDialogmemberMember 287643918 Sep '08 - 5:41 
Hi,
 
I´m trying to find the problem. Now I think i´m near the location.
 
The function that I think is: "bool CFileTreeCtrl::FillTreeView (LPSHELLFOLDER lpsf, LPITEMIDLIST lpifq, HTREEITEM hParent)"
 
The statment may be this: "if (!GetName(lpsf, lpi, SHGDN_FORPARSING, Path))
goto Done;"
 
Because if I change this statment to commentary this is OK, but GetSelectFiles or GetSelectFolders buttons doesn´t work, I don't know why.
 
Thanks Victor!
GeneralRe: When Running FileTreeDialogmemberVictor Ricklefs18 Sep '08 - 6:59 
Should not be a problem. I wrote the code almost 3 years ago and am not sure now where the problem is. As I remember, it does not use any threads that could run in the background... Which version of Visual Studio are you using? I rememeber there was some problem running it in a debug mode, but am not sure. Does it hang when you open and close it immediately, or only after you do something with it?
GeneralRe: When Running FileTreeDialogmemberMember 287643918 Sep '08 - 9:38 
OK Victor!
 
I had trying to know what happened with this.
So, I'll try to explain my conclusions.
In this function "BOOL CFileTreeCtrl::GetName (...",
if I to eliminate some code like this:
//if (NOERROR==lpsf->GetDisplayNameOf
(lpi,dwFlags,&str))
//{
LPTSTR lpStr;
StrRetToStr(&str,lpi,&lpStr);
strName = lpStr;
CoTaskMemFree(lpStr);
//}
 
FileTreeCtrl.cpp
BOOL CFileTreeCtrl::GetName (LPSHELLFOLDER lpsf, LPITEMIDLIST lpi,
DWORD dwFlags, CString &strName)
{
BOOL bSuccess=TRUE;
STRRET str;
 
if (NOERROR==lpsf->GetDisplayNameOf(lpi,dwFlags,&str))
{
LPTSTR lpStr;
StrRetToStr(&str,lpi,&lpStr);
strName = lpStr;
CoTaskMemFree(lpStr);
}
else
bSuccess = FALSE;

return bSuccess;
}
of course the programm doesn't work well, but that problem disappears.
So I think the problem may be in the function "GetDisplayNameOf",
or some value in the arguments i'm not sure or may be on my system, my compiler version is Visual c++ 6.0.
 
Thank Very Much Victor.
GeneralRe: When Running FileTreeDialogmemberNagender19 Feb '09 - 5:02 
did you find any solution to this? i think it might have to do with freeing up resources after the call.
Questionquestion about multiple selection files & folders (not expanded)memberzikzik22 May '08 - 5:58 
First of all. Congratulations for your work, very excellent!!!
 
So, when I begin to use the demo program, I proceed like that :
 
- I launch the soft
- I select (with http://www.codeproject.com/KB/tree/FileTreeCtrl/check05.jpg[^] entire folder (which contain some folders and files), but when I click "GetSelectedFiles"
- I click into "GetSelectedFolders", no files were displayed in info box ("None").
 
But when, I expand all the node, all files and folders are checked, when I see some files in the file dialog, they appear into file selection info.
 
Thanks in advance.
AnswerRe: question about multiple selection files & folders (not expanded)memberVictor Ricklefs23 May '08 - 4:48 
That's correct. At least it was designed this way. It shows files only when the node was expanded. Otherwise it shows only the path to the folder in which you need to search files yourself....
QuestionVery very nice...what about correct nr of sel.files?memberrootdial13 Jun '07 - 12:24 
First of all i want to say "Wow, thats what i was looking for!".
U did a great work here.
 
So far i am not sure if its a bug or i understand something wrong here.
If i chose a Folder which contains several files in it, i cant display
the numbers of files in it. I first have to open the folder, after that
the number of found files can be seen.
 
I hope u understand what i mean Smile | :) If you could fix that one to a permanent
count of selected files (over all folders), it would be perfect!
AnswerRe: Very very nice...what about correct nr of sel.files?memberVictor Ricklefs13 Jun '07 - 17:49 
Sorry, that's not a bug... That is a feature. File tree control is not designed to count files, it only displays and allows to select files and folders. I have a separate util that looks up the files in a folder and counts them, but it is not included into the code. And, actually, I have found this util somewhere on a CodeProject. I can look it up and give the exact link later...
GeneralRe: Very very nice...what about correct nr of sel.files?memberrootdial13 Jun '07 - 19:20 
Hi,
 
so i can select multiple Files but cant use them
in my program progess for further actions?
 
The selection of files makes only sence if i chose only 1 Folder and open it?
Right?!
 
The selection of folders itself is the main thing as i understand it so far.
 
Anyway it helped me out a lot. To count the files isnt that hard if i got
the path i am playing with Smile | :)
 
Thanks Victor!
 

GeneralRe: Very very nice...what about correct nr of sel.files?memberVictor Ricklefs14 Jun '07 - 6:07 
Thanks for your comment!
Check out the link http://www.codeproject.com/file/cfilefinderex.asp[^]
Very nice class for finding files and doing smth with found files....
 
Yeah, u r right - the primary purpose for my code is to allow you select the files and folders...
GeneralMany thanks [modified] But grandchild!memberhuyvqson30 May '07 - 0:11 
It's very nice!
But it took me a very long time to understand. Big Grin | :-D
 
Yeah, I had tried to scan my tree but it stopped at child item.
For example, I have tree C:\Test\Child\GrandChild
And I scan this tree like:
HTREEITEM hRoot, hTest, hChild, hGrandChild;
hRoot = GetRootItem(); \\ C:\
hTest = GetChildItem(hRoot); \\ C:\Test
hChild = GetChildItem(hTest ); \\ C:\Test\Child
hGrandChild = GetChildItem(hChild ); \\ C:\Test\Child\GrandChild
 
I don'n understand why I cannot retrieve hGrandChild Item like above. Please help!
 
-- modified at 2:31 Tuesday 5th June, 2007

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web01 | 2.6.130523.1 | Last Updated 4 Jun 2007
Article Copyright 2006 by Victor Ricklefs
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid