Folder/Drive Picker Combo Box



There are three main things that this CFolderComboBox class does. First, the class displays text with bitmap images in a hierarchical display. Second, the class gets all of the drives on a system using _chdrive to determine if a drive is present. Finally, the CFolderComboBox returns the relative path of a selected folder or drive.

SETUP

In order to use this class in your own project, you must be sure to add the bitmap resources (one for normal and one for disabled) for the different folders to your project. You will have to name the file Folders.bmp as IDB_FOLDERS in the resource file and you will have to name Folders_Disabled.bmp as IDB_FOLDERS_DISABLED in the resource file as well. When adding a combo box to your project, please make sure the following styles are set:

1) Has Strings should be checked.
2) Set to Owner Draw Fixed
3) Turn off sort

The rest of the defaults should be OK. In addition, please be sure to define the following resource strings which are loaded to fill up the combo box.

IDS_DOCUMENTFOLDERS	Document Folders
IDS_PERSONAL		My Documents
IDS_FAVORITES		My Favorites
IDS_PATH		System Path
IDS_DESKTOP		Desktop
IDS_FONTS		Fonts
IDS_MYCOMPUTER		My Computer
IDS_SYSTEMFOLDERS	System Folders
IDS_LOCALHARDRIVES	Local Hard Drives

After that, add the source files (FolderCombo.h and FolderCombo.cpp) to your project. Next, add the #include FolderCombo.h directive to your source file. Then create a class variable of type CFolderComboBox. The only actual code you will have to call is GetSelectedPathName which will return a CString with the pathname of the selected folder. If no item is selected, an empty CString will be returned. If you selected a folder that contains subfolders (for example, My Computer), this will return all paths separated by semicolons (e.g. C:\;D:\;E:\, etc.). By the way, if you want to disable the control, the painting for this is handled automatically.

This code was compiled with Visual C++ 6.0. I didn't test it with UNICODE, but it should work. Also, I didn't test this on anything but Windows 98, but it should work on Windows 95. If you modify this code at all to support some of the 5.0 version of the Shell CSIDL constants, please note that this won't work on systems that don't have this Shell version. The Visual C++ documentation has the definitions of all of the different CSIDL constants.

BACKGROUND

The internal structure of the CFolderComboBox is shown here:

typedef struct SFolder
{
  int m_iImageIndex;      // Index of picture in image list
  int m_iIndent;          // Indentation index
  CString m_sFolderName;  // Descriptive name of folder
  CString m_sPathName;    // Actual full pathname of folder(s)

} SFOLDER, *LPSFOLDER;

To determine if a Windows 95/98 standard folder exists, the following code fragment was used:
if(SUCCEEDED(SHGetSpecialFolderPath(NULL, szPath,
CSIDL_PERSONAL, FALSE)))
{
// Do something now that we have the
// "My Documents" directory
}

To get the actual relative pathname of the selected item, a call to GetSelectedPathName() is all that is needed. This will return a CString with the relative pathname of the selected folder location.

AFTERTHOUGHTS

Please note that this class could definitely be upgraded. There are still some features that are missing, and some that could be enhanced, such as the following:

1) Ability to get actual network names instead of just drive letters. That is, every item in Network Neighborhood that doesn't necessarily have a drive attached. Maybe specify by a flag how it should handle network drives.

2) Ability to draw the bitmap in the text box area of the combo box as well as in the drop-down list.

3) Create a special highlite bitmap in addition to the standard and disabled bitmaps that shows the correct masked image when and item is selected. In fact, using only one standard bitmap, and then masks for different states could also be done.

4) Unlike Windows, this class does not no if the hardware changed (i.e. disk insert or remove). It could be upgraded to rescan the drives when the hardware changes, or it could be continually done in a background thread.

5) I didn't use all of the CSIDL constants for standard Windows folders. Some more could be added, as well as the shell32 5.0 specific constants.

6) And of course, it could always be optimized. When the CFolderComboBox is initialized, it attempts to _chdrive to the floppies, which of course makes an annoying sound if no floppy is in the drive. The drives could be added without really scanning them.

Download demo project - 32 KB

Download source - 6 KB



Comments

  • Nice!!

    Posted by Mr.Prakash on 03/06/2004 11:34am

    its quite good thing to have in once software lib.

    Reply
  • Removable drive issue..

    Posted by Legacy on 11/14/2002 12:00am

    Originally posted by: Michael Shamgar


    Im using 'SHBrowseForFolder', and have managed to work around all the issues with it, except for one :

    I have two 'removable drives' (actually drives that map to my flash card reader, for my digital camera).

    Everytime the dialog opens, or attempts to scroll up/down near these drives, it tries to access them, but can't - because there are no devices in them. As a result it pops up the classic :

    'There is no disk in the drive. Please insert a disk..'

    Cancel/TryAgain/Continue

    (etc..)

    has anyone come across this, or have a solution for fixing it?

    Mike

    Reply
  • Relative Paths

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

    Originally posted by: Paul Marston

    I recently had to write part of an application that would accept an addition of relative paths to an existing directory under win NT 4.

    Unfortunately, the SHCreateDirectoryEx is unavailable to NT (only 2K and above :<)

    The way I got around this, was to simply break the directory string down (using CString [x]), and analysing if there was a \ or // or . etc.

    This meant that I could use a simple if else chain to analyse whether or not the relative path should be added or removed.

    For example:

    user Path ..\Fred
    Existing path D:\Bod\app.exe

    became D:\Fred\app.exe

    It is clunky, and I am sure that there are hundreds of holes in it, but it works on NT !

    More importantly, it is fairly straightforward to do...

    Reply
  • How to add all driver path to it?

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

    Originally posted by: bennyfan

    Yeah, it's very great,but how can I add all my driver path to it, so I can select it just like Windows Explorer!
    

    Reply
  • ITs working perfect in Win2K

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

    Originally posted by: Sarath Bhooshan S

    ITs working perfect in Win2000 Professional. Thanks a lot

    Reply
  • Controls

    Posted by Legacy on 04/17/2001 12:00am

    Originally posted by: kenshee

    Is there any way I could get the system to scan if the flopppy or any drives are used using MFC??Thanks..

    Reply
  • Suggestion #3 - Highlighted icons

    Posted by Legacy on 05/29/2000 12:00am

    Originally posted by: Sebastien Martin

    I built a similar class as the one posted here using only API functions, but I couldn't figure out how to make the icons highlighted. (Not just turning every second pixel to a blue color, but acutally shading every pixel to a shade of blue like Win98/NT4/2K do. The original author mentioned something about masks but I'm still kind of new to image manipulation. Even if you provide an MFC solution, I could probably base my code on it and get it working with win GDI. Thanks.

    Reply
  • SHBrowseForFolder - full example

    Posted by Legacy on 10/19/1999 12:00am

    Originally posted by: David Netherwood

    Following Tobias Sch�nherr's suggestion I used the SHBrowseForFolder to pick a directory. I works fine, but there is quite a bit of work goes into to getting it work smoothly, so I thought I'd post a fuller example.


    #include <windows.h>
    #include <shlobj.h>
    #include <iostream.h>


    // call back function
    // we only se it to set the current directory
    int CALLBACK BrowseCallbackProc(HWND hwnd, UINT uMsg, LPARAM , char* path)
    {
    switch (uMsg)
    {
    case BFFM_INITIALIZED:
    // Driretory browser intializing - tell it where to start from
    PostMessage (hwnd, BFFM_SETSELECTION, TRUE, (LPARAM)path);
    break;
    }
    return 0;
    }


    int main(int argc, char** argv)
    {
    // Browser parameter block
    BROWSEINFO bi;
    memset (&bi, 0, sizeof(bi));


    // Path variable
    char path[_MAX_PATH] = "C:\\Temp";

    // Initialize COM
    CoInitialize(NULL);

    // Get root point to browse from
    // Can use NULL for all - which in effect is what we are doing here
    LPITEMIDLIST pidlRoot = NULL;
    SHGetSpecialFolderLocation(HWND_DESKTOP, CSIDL_DESKTOP /*CSIDL_DRIVES*/, &pidlRoot);

    // Setup Browse parameter block
    bi.pidlRoot = pidlRoot;
    bi.ulFlags = BIF_RETURNONLYFSDIRS;
    bi.lpfn = (BFFCALLBACK)BrowseCallbackProc;
    bi.lParam = (LPARAM)path;

    // Call browse
    LPITEMIDLIST Selection;
    Selection = SHBrowseForFolder(&bi);

    // If went OK, decode return to produce the selected path
    if (!NULL)
    SHGetPathFromIDList(Selection, path);

    // Now free up the memory allocated by the various COM
    // objects we accessed indirectly
    LPMALLOC lpMalloc = NULL;
    if (!SHGetMalloc(&lpMalloc) && (NULL != lpMalloc))
    {
    if (pidlRoot)
    lpMalloc->Free(pidlRoot);
    if (Selection)
    lpMalloc->Free(Selection);
    }

    // Print path to console
    cout << path << endl;
    return 0;
    }


    Reply
  • Don't work with VC++5 and Windows98 !!!!

    Posted by Legacy on 04/16/1999 12:00am

    Originally posted by: TERAHI

    No comment....

    Reply
  • Not a text box

    Posted by Legacy on 01/25/1999 12:00am

    Originally posted by: Xiaolong Wu

    this comment concerns the author's improvement plan #2. the plan is to add icons to the edit box. if we have a closer look at the "combobox" on the top of the CFileDiaolog, we can see that it is not a usual CComboBox. the original edit box is replaced by a CButton. one cannot type in it. When one clicks on it, it behaves just like the arrow button on the right.

    so for the author's improvement plan #2, we need to combine two buttons and a CListBox.the CListBox will be hiden most of the time until user clicks on the buttons.

    I tried to install a button on a combobox to cover the editbox. but didn't work. when the combobox gets focus, the button dispeared. CComboBox does not give us a handle to the edit box. CComboBoxEx does, but the item data stucture is quite different.


    xiaolong wu

    Reply
  • Loading, Please Wait ...

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

Top White Papers and Webcasts

  • On-demand Event Event Date: September 10, 2014 Modern mobile applications connect systems-of-engagement (mobile apps) with systems-of-record (traditional IT) to deliver new and innovative business value. But the lifecycle for development of mobile apps is also new and different. Emerging trends in mobile development call for faster delivery of incremental features, coupled with feedback from the users of the app "in the wild." This loop of continuous delivery and continuous feedback is how the best mobile …

  • The explosion in mobile devices and applications has generated a great deal of interest in APIs. Today's businesses are under increased pressure to make it easy to build apps, supply tools to help developers work more quickly, and deploy operational analytics so they can track users, developers, application performance, and more. Apigee Edge provides comprehensive API delivery tools and both operational and business-level analytics in an integrated platform. It is available as on-premise software or through …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds