Thread safe Directory browser

I admire all the efforts done in this line of directory tree controls in the
recent past — Nicola Delfino (Directory browser), Kirk
Stowell(MFC Extension classes..) and many more.

Unfortunately I cannot add the code to my existing
projects as my code is multithreaded and uses different logic. With
more people showing interest in this line directory tree controls
I hope my code would be found useful by somebody.

What the code does:

The code basically displays all current drives (including mapped
drives) in the PC in which it is running, provides option to view
only directories or files&directories, option to display only
filtered files (*.exe, *.txt etc.,) and finally allows you to select
directory/file (Multiple file selection is presently not
supported) by double clicking on the item. Apart from directory
tree control, the code also offers a way to give form view the
look&feel of a dialog box, a feature which may be helpful to those who
wants SDI application looking like a dialog box.

Integration with existing code:

The CDirTreeCtrl is totally independent and can be used by just
inserting into your project except for the following additions:

  1. place the preprocessor macro #define _WIN32_WINNT 0x0400
    before all other ".h" #includes in stdafx.h. This is
    required to call the Win32 function ReadDirectoryChangesW().
    However, this macro should be there already if you are using
    UNICODE/COM/DCOM application.

  2. change of application header file name in DirTreeCtrl.cpp

How it differs with existing ones:

Compared to other tree controls and in the site and even
SHBrowseForFolder(), the major difference in this tree control is
it is entirely dynamic as far as local drives are concerned,
thanks to the Win32 function ReadDirectoryChangesW(). Remote
drive updation is not entirely dynamic. Also it is
convenient/necessary (as it happened with me) to show files also
in the directory hierarchy to select them. Once the multiple file
selection feature is added (which I shall do as soon as possible
after the acceptance/response) it means selecting files from
different directories at a time, a feature which is not possible
in common file selection dialog.

However I am showing the same image for all types of files as reading
the icon image from file system likely to keep CImageList member
variable low in memory requirement. I appreciate that other tree
controls achieved this nicely.

UNICODE:

The code doesn’t work under UNICODE as I have hard coded all the
strings as ANSI (I should have used TCHAR!)

Environment

It is built is VC++ 5.0 (MFC 4.21) and tested only on Windows
NT workstation 4.0 with Service Pack 3.

How the code works:-

As I am providing the control class as it is, I would like to
mention only the main logic here.

The main logic with the directory tree is to Parse the directory
only when the user expands it (this is similar to Windows
explorer and other directory trees). This saves lot of of waiting
time when the application is initially shown. This is possible by
calling CTreeCtrl’s member function GetItemState().

So in CDirTreeCtrl::OnItemExpanding(NMHDR* pNMHDR, LRESULT*
pResult) the code appears as below:


UINT nMask = GetItemState((pNMTreeView ->
itemNew).hItem,TVIS_EXPANDEDONCE);

if (!(nMask & TVIS_EXPANDEDONCE)) //the item is first time expanding
{
//…….
FillItem();
//….
}

If user wishes to see files also AND wishes to change the file
filter, tree is updated.
(In fact only the current drive the user is working with is
updated–This may not be very user friendly, but I had to do this
for performance reasons. Otherwise it is likely that the tree to
eat up too much memory and also make the user wait for quite a
long time for the sand cursor to go off)

Showing Files may be turned off/on using void
CDirTreeCtrl::SetFileFlag(BOOL i_bFileFlag)

Changing file filter can be provided by calling
void CDirTreeCtrl::SetFilter(CString strFilter).
Of course, this has no effect if file flag is turned off.

But none of these functions will directly update the tree unless
you call explicitly void CDirTreeCtrl::UpdateTree(). Updation is
also possible by pressing F5 key with focus on Tree control.

UpdateTree() updates drive information (some drives might have
unmapped or newly mapped).
and sets currently shown sub-directories state by calling
SetSubDirState(HTREEITEM hItem).

Dynamic updation of tree (for both directories and files) is done
by monitoring each drive (not remote) in a separate thread and
call for Tree Updation as soon as a change is reported. Semaphore
object is used for Thread Synchronization. The Thread function is
made as a static member so as keep it bound with the class
(global function can be misplaced!)

The Win32 function ReadDirectoryChangesW() is used in Synchronous
mode to monitor the changes of a given drive. Though the function
works in UNICODE I have converted the returned string to ANSI and
so will not force your application to be UNICODE enabled.

I would be thankful for any comments/report on this multithreaded
behavior.

Please be free to mail me regarding any features/bugs to Mail ID
provided in About Box.

With regards,
Achalla Srinivasu. ([email protected])

Download demo project – 40 Kb

Download source – 15 Kb

More by Author

Must Read