Browse for Folder with a Quick Pick

Introduction

I was working on the SizeMe project when a user requested a feature. He asked for a predefined list over directories that he wanted to scan. I had just finished reading the article Customizing the "Browse for folder" dialog, and I got the idea to just to customize the common dialog. Here is the result.

Remember that the common dialogs are shown in the installed language of Windows. The picture shows the dialog with my language, Norwegian. I also want to thank Hans Dietrich for his article XBrowseForFolder - Wrapper for SHBrowseForFolder; some of the code used in the project has been inspired by his work.

Using the Code

The project can be used in either a MFC project or Win32. (The project has only been tested with the VS6.0 environment. I don't know whether it would work on the never versions of Visual Studio, but I guess so.) First, add the files Dirbrowse.cpp and DirBrowse.h to your project, and then include DirBrowse.h. There are two public functions that you need to use:

BOOL Show(char *szInitDir="");

Function Show results in TRUE if the user pressed OK, and FALSE on cancel/close. The szInitDir is optional and selects the startdir for the browser.

char* GetSelectedDir();

Function GetSelectedDir returns a string with the selected path.

Sample

Here is the quick Win32 sample I wrote to handle the class:

#include "stdafx.h"
#include "..\DirBrowse.h"

#include <stdio.h>

int APIENTRY WinMain(HINSTANCE hInstance,
                     HINSTANCE hPrevInstance,
                     LPSTR     lpCmdLine,
                     int       nCmdShow)
{
   // TODO: Place code here.
   CDirBrowse m_dirbrowser(NULL, hInstance);

   if(m_dirbrowser.Show()==TRUE)
   {
      char Text[MAX_PATH*2];
      sprintf(Text, "You selected folder: %s",
              m_dirbrowser.GetSelectedDir());
              MessageBox(NULL, Text, "Browse for folder", MB_OK);
   }
   else
   {
      MessageBox(NULL, "You pressed the cancel button!",
                 "Browse for folder", MB_OK);
   }

   return 0;
}

It is as simple as that. Take a look at the project to check out the MFC version of the same.

Header Customization

When I create classes that can be reused, I always create a lot of #defines. This class is no exception. Here is the defines list:

//#1
#define BROWSE_WIDTH                    640
#define BROWSE_HEIGHT                   420
#define BROWSE_LISTVIEW_SIZE            0.65
#define BROWSE_BORDER_VERT              4
#define BROWSE_BORDER_HORI              2
#define BROWSE_MAXENTRIES               20


//#2
//This is the message that we start with
#define BROWSE_MESSAGE                  10101

//#3
//The name of our hypertext class
#define STATIC_HYPERTEXT_WINDOW_CLASS   "STATIC_HYPERTEXT"

//#4
//This is the font & size we use for showing the info
#define BROWSE_FONTNAME                 "Verdana"
#define BROWSE_FONTSIZE                 12

//#5
//The colors used
#define BROWSE_SELECTCOLOR              RGB(0,0,255)
#define BROWSE_SELECTCOLORHOVER         RGB(50,105,255)
#define BROWSE_DIRCOLOR                 RGB(0,0,200)
#define BROWSE_DIRCOLORHOVER            RGB(100,100,250)

//#6
//The registry variables
#define BROWSE_REGISTRY_ROOT            HKEY_CURRENT_USER
#define BROWSE_REGISTRY_PATH            "Software\\DirBrowser"

//#7
//Strings used
#define BROWSE_TEXT_SHORTCUTS           "Shortcuts"
#define BROWSE_TEXT_HELP                "Please select a folder in
   the list and press the arrow to save the directory for a
   quickpick later on"
#define BROWSE_TEXT_HELP_CAPTION        "Browse for folder help"
#define BROWSE_TEXT_HELP_TOOLTIP        "Press this to save selected
                                         path as a shortcut"
   //Must not exceed 79 chars!!!

Each group is explained below:

Group #1
Defines Description Default Value
BROWSE_WIDTH, BROWSE_HEIGHT, BROWSE_LISTVIEWSIZE The WIDTH/HEIGHT is the size of the window. The ListView-size is the percentage of the width of the dirlist. 640, 420, 0.65 (percentage of the width!)
BROWSE_BORDER_VERT, BROWSE_BORDER_HORI The border variables is pixels between controls in vertical and horizontal directions. 4,2
BROWSE_MAXENTRIES MaxEntries is the size of quick picks you can show on the screen (shouldn't be more entries than the screen can show) 20 (should be enough for everybody)
Group #2
BROWSE_MESSAGE Message is the internal message that you use for the controls. It is used increased, so it start on 10101, then 10102 and so on 10101
Group #3
STATIC_HYPERTEXT_WINDOW_CLASS The Hypertext window class is the internal name of the class handling the hypertext-class. Just change this if you have duplicated names in the project. "STATIC_HYPERTEXT"
Group #4
BROWSE_FONTNAME, BROWSE_FONTSIZE This is the font & size used in the hypertext class. It will not check whether the font actually exists, so be sure to enter a valid name. "Verdana", 12
Group #5
BROWSE_SELECTCOLOR, BROWSE_SELECTCOLORHOVER, BROWSE_DIRCOLOR, BROWSE_DIRCOLORHOVER Colors on the hypertext class. Split into the selector and the actual directory. RGB(0,0,255), RGB(50,105,255), RGB(0,0,200), RGB(100,100,250)
Group #6
BROWSE_REGISTRY_ROOT, BROWSE_REGISTRY_PATH The path to where you want the config to be saved. This is usually changed because you don't want the dirbrowser to load variables stored in the same place in your different projects where you use this. HKEY_CURRENT_USER, "Software\\DirBrowser" (This should always be changed!)
Group #7
BROWSE_TEXT_SHORTCUTS, BROWSE_TEXT_HELP, BROWSE_TEXT_HELP_CAPTION, BROWSE_TEXT_HELP_TOOLTIP Because I haven't made "Multilanguage" support for this project, you can change the text used here. "Shortcuts", "Please select a folder in the list and press the arrow to save the directory for a quickpick later on", "Browse for folder help", "Press this to save selected path as a shortcut" (Must not exceed 79 chars)

Points of Interest

I found a little bug when compiling the release version of the project. Take a look at this code:

if(pMe->MessageIsOdd == FALSE)
{
   if(nID % 2 == 0)
      MsgIsOdd = FALSE;
   else
      MsgIsOdd = TRUE;
}
else
{
   if(nID % 2 == 0)
      MsgIsOdd = TRUE;
   else
      MsgIsOdd = FALSE;
}

There shouldn't be any errors on this, but after some research I noticed that the first part of the if-sentence is the only one that gets called. I needed to split them to avoid this bug, like this:

if(pMe->MessageIsOdd == FALSE)
{
   //...
}
if(pMe->MessageIsOdd == TRUE)
{
   //...
}

If someone have a good answer about this, please let me know. I'm using VS6.0 C++ with the SP5 + UINT64 Processor Pack patch.

History

v1.0 - Initial release



About the Author

Lars Werner

Thnx for viewing my article...

Check out some of my projects:

http://lars.werner.no/sizeme/ - Ultimate tool for maximize your output on CD/DVDs!

http://lars.werner.no/unpacker/ - Auto extract of multiple archives (RAR/ZIP) with queue support and cleanup options!

http://lars.werner.no/vnc/ - Fullscreen captionbar modified VNC clones (RealVNC, UltraVNC and TightVNC)

Visit http://lars.werner.no/ for more info!

Downloads

Comments

  • There are no comments yet. Be the first to comment!

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

Top White Papers and Webcasts

  • Live Event Date: May 6, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT While you likely have very good reasons for remaining on WinXP after end of support -- an estimated 20-30% of worldwide devices still are -- the bottom line is your security risk is now significant. In the absence of security patches, attackers will certainly turn their attention to this new opportunity. Join Lumension Vice President Paul Zimski in this one-hour webcast to discuss risk and, more importantly, 5 pragmatic risk mitigation techniques …

  • Given today's threat environment and the increasing connectivity of digital infrastructures, security teams now realize that they must assume their IT environments are subject to periodic compromise. Gone are the days when preventive measures to secure the perimeter or trying to detect malware problems using signature-match technologies were enough. New practices based on an understanding of the phases of an attack, continuous threat monitoring, and rapid attack detection and remediation are necessary. This …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds