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

Download demo project - 40 Kb

Download source - 15 Kb



Comments

  • Новый сервер Lineage 2 для новичков!

    Posted by Pumvedoreosse on 03/01/2013 06:23am

    http://la2start.com/ - новый сервер Lineage 2 High Five для новичков! Заходите и присоединяйтесь! Лучшая игра всех времен! Мы только что открылись! Рейты х100 (крафт-пвп сервер)

    Reply
  • Thank you

    Posted by Legacy on 11/25/2003 12:00am

    Originally posted by: jose

    OK

    i define the bordel of :

    #define _WIN32_WINNT 0x0400

    in stdafx.h before all

    Thanks

    Reply
  • ReadDirectoryChangesW Not Giving Consistent Notification

    Posted by Legacy on 02/09/2003 12:00am

    Originally posted by: Efrat

    Hi,
    thanks for the usefull code.
    i want to ask u if know that ReadDirectoryChangesW with FILE_NOTIFY_CHANGE_FILE_NAME is not giving consistent notification. it sometime misses files.
    if u encountered this problem, do u know about a workaround or a another similar method?

    efrat

    Reply
  • Thank you!

    Posted by Legacy on 12/08/2002 12:00am

    Originally posted by: Ruslan Teluk

    Thank!

    Reply
  • What about Network Neighborhood?

    Posted by Legacy on 05/01/2002 12:00am

    Originally posted by: anil

    But it does't show Network Neighborhood?
    it shows only if mapped !
    but it is far backward than windows explorer
    more work is required .
    if anyone have solution (in vc++)
    pl. send it to me at anil003@hotmail.com
    bye

    Reply
  • Leak

    Posted by Legacy on 12/23/2001 12:00am

    Originally posted by: DMD

    Ive been leaking. Ooops. I mean that there are many memory leaks within this app code

    Reply
  • 谢谢

    Posted by Legacy on 11/27/2001 12:00am

    Originally posted by: 孤独的行路者

    看了你的代码,不错,正用得上,多谢!
    还想向你请教响应Check消息的操作!

    Reply
  • Thank you.

    Posted by Legacy on 09/20/2001 12:00am

    Originally posted by: VMB

    I was racking my brain on why I kept getting a compile error 2605 when attempting to us ReadDirectoryChangesW().  Thank for putting this project here.
    
    

    I am new to this fuction. The NextEntryOffByte is the number of bytes to be skipped to get to the next record. Does that mean you can (somehow) scroll through and get information on more files, if they exist?

    Thanks again

    Reply
  • How to initialize your starting directory

    Posted by Legacy on 05/03/2001 12:00am

    Originally posted by: Alex Huber

    This control was great, but I wanted to start in a particular directory and center the scrollbar on that directory.  It only required modifying the Init and InitDriveInfo functions to take in a CString, and a path parsing function.  This is how I managed to do it. (Note, ... indicates code deleted for brevity)
    
    

    void CDirTreeCtrl::Init(CString initdir)
    {
    ...
    //Pass in the initdir to set up a directory
    InitDriveInfo(initdir);
    }

    In the InitDriveInfo function I added the following code to the bottom of the function. This will call a function ParsePath (taken from code posted by John McTainsh on this web site)

    void CDirTreeCtrl::InitDriveInfo(CString initDir)
    {
    ...
    HTREEITEM hDriveItem = GetDriveItem((LPCSTR)initDir);

    //
    //Expand the Tree to the Inital Path.
    //
    int nLevel = 0;
    CString sDirName;
    HTREEITEM hCurrent = hRootItem; //Current item in the list being expanded.
    if( initDir.IsEmpty() )
    initDir = _T("C:\\"); //if nothing is passed in, default to c:\

    while( ParsePath( initDir, nLevel, &sDirName ) )
    {
    //Search for the matching tree item and expand
    HTREEITEM hItem = GetChildItem( hCurrent );
    while( hItem )
    {
    if( sDirName.CompareNoCase( GetItemText( hItem ) ) == 0 )
    {
    hCurrent = hItem;
    Expand( hCurrent, TVE_EXPAND );
    EnsureVisible(hCurrent); //centers control onto the current directory
    break;
    }
    hItem = GetNextSiblingItem( hItem );
    }
    nLevel++;
    }
    }

    //find the passed in path
    bool CDirTreeCtrl::ParsePath( CString sPath, int nLevel, CString *const psDirName )
    {
    //find first match
    int nStart = 0; //Location in sPath to search from
    while( nLevel )
    {
    nStart = sPath.Find( _T('\\'), nStart );
    if( nStart < 0 )
    return false;
    nLevel--;
    nStart++;
    }
    //We now have the start point to find the end.
    int nEnd = sPath.Find( _T('\\'), nStart );
    if( nEnd < 0 )
    *psDirName = sPath.Mid( nStart );
    else
    *psDirName = sPath.Mid( nStart, nEnd-nStart);

    //if we have a c: psDirName, append a \\ to make it 'c:\'
    if ((*psDirName).Right(1) == _T(":"))
    *psDirName += "\\";

    return true;
    }


    I hope this helps someone out.

    Reply
  • TreeView

    Posted by Legacy on 12/21/2000 12:00am

    Originally posted by: Alejandro

    Hi.
    If have been spoting what you did and it was nearly what I was looking for.
    I'm triyng to use a treeview control in Visual Basic and see the directory tree.
    Can you convert it to a control or you know the way to do what i want to do with the VB treeview control ???

    Thank's ... great job !!
    Al.

    Reply
  • Loading, Please Wait ...

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Live Event Date: October 23, 2014 @ 12:00 p.m. ET / 9:00 a.m. PT Despite the current "virtualize everything" mentality, there are advantages to utilizing physical hardware for certain tasks. This is especially true for backups. In many cases, it is clearly in an organization's best interest to make use of physical, purpose-built backup appliances rather than relying on virtual backup software (VBA - Virtual Backup Appliances). Join us for this eSeminar to learn why physical appliances are preferable to …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds