dcsimg

Thread safe Directory browser

WEBINAR:
On-Demand

Desktop-as-a-Service Designed for Any Cloud ? Nutanix Frame


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. (mattakeri@hotmail.com)

Download demo project - 40 Kb

Download source - 15 Kb



Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date