Click here to Skip to main content
15,867,453 members
Articles / Desktop Programming / MFC

XFolderDialog - a folder selection dialog based on CFileDialog

Rate me:
Please Sign up or sign in to vote.
4.90/5 (56 votes)
2 Jun 2010CPOL7 min read 439.5K   5.5K   138   135
XFolderDialog provides a folder selection dialog like that used in MS Word, and includes persistent list view type.

Introduction

My Project Manager recently asked me why our folder selection dialog didn't look the same as the one in Microsoft Word®. This question took me by surprise, since we have been using my XBrowseForFolder dialog for several years:

screenshot

When I looked at the dialog in Microsoft Word, I saw that my Project Manager was right. This is what I found:

screenshot

screenshot While this looks superficially like CFileDialog, using HPS HwndSpy shows that it is entirely different. Instead of being dialog-based, Word uses a window whose class is "bosa_sdm_Microsoft Word 9.0". And instead of using a standard SysListView32 list control, the one in Word has a class name of "OpenListView":

What would it take to display a folder selection dialog like Word's? Would it be possible to do the same thing using CFileDialog? These questions were in my mind as I studied the folder selection window in Word.

A Journey Into CFileDialog

The most obvious thing to say about a folder selection dialog is that it should display only folders, not files. I tried a number of tricks that had the desired effect, but also were pretty slow. In the end I used a filter for the file extension - one that was generated by guidgen.

The next thing to take care of was the places bar - the toolbar with icons that is displayed on the left in the above screenshot. Fortunately Paul DiLascia's article on the Windows 2000-style file open dialog shows a simple way to do this.

XFolderDialog allows you to select the style of open file dialog by specifying the OS version - OS versions before Windows 2000 do not support the places bar. You can also specify "OS autodetect", which will display the places bar whenever possible.

The following screenshots show the demo program and how XFolderDialog will appear from Windows 98 to Vista, using OS autodetect:

Click to enlarge.
98 screenshot screenshot
2000 screenshot screenshot
XP screenshot screenshot
Vista screenshot screenshot

FEATURE NOTE

Setting OS to 5 on Windows 98 will not work - XFolderDialog will not display.

Of course, you can "downgrade" to OS version 4 on Windows 2000, XP, and Vista. Here is what OS version 4 XFolderDialog looks like on XP:

screenshot

Persistent List View Mode

screenshot
screenshot Starting with version 1.3, XFolderDialog supports persistent list view mode for XP and Vista. "Persistent list view mode" refers to the view that you see when the list is displaying folders. As you see from the screenshot, for XP it can be set to one of five types of view. With the standard Windows Open dialog on XP, this view is not persistent - it will always open in List mode.

XFolderDialog provides two mechanisms for persisting the list view mode:

  1. Persistence via registry/INI file - the view mode will be restored from the registry/INI file when XFolderDialog is displayed, and saved when it is closed. This happens completely automatically and is the default, unless you change it by API call. If using the registry, the view mode will be restored/saved using the key

    HKEY_CURRENT_USER\Software\<Company>\<App Name>\XFolderDialog\ViewMode

    For example, the key for XFolderDialogTest.exe is

    HKEY_CURRENT_USER\Software\CodeProject\XFolderDialogTest\XFolderDialog\ViewMode

    and was set by this code in XFolderDialogTest.cpp:
    SetRegistryKey(_T("CodeProject"));
    
  2. Persistence via API calls - if you do not want to use the built-in mechanism for restoring/saving the view mode, you can use the GetViewMode()/SetViewMode() functions. It is then up to you to load and save the view mode.

screenshot Persistent list view mode is also supported for Vista, which has seven view modes vs. five for XP. Just as for XP, XFolderDialog running on Vista provides two mechanisms for persisting the list view mode. Unlike XP, Vista itself persists the list view mode, and so it isn't necessary for your program to do it (although it will work correctly on Vista if you do want to use the XFolderDialog persistence mechanisms).

The following table shows list view modes:

View ModeXPVista
XLVM_XP_DO_NOT_PERSIST Image 16Image 17
XLVM_XP_UNDEFINED Image 18Image 19
XLVM_XP_ICONS Image 20Image 21
XLVM_XP_LIST Image 22Image 23
XLVM_XP_DETAILS Image 24Image 25
XLVM_XP_THUMBNAILS Image 26Image 27
XLVM_XP_TILES Image 28Image 29
XLVM_VISTA_DO_NOT_PERSIST Image 30Image 31
XLVM_VISTA_UNDEFINED Image 32Image 33
XLVM_VISTA_DETAILS Image 34Image 35
XLVM_VISTA_TILES Image 36Image 37
XLVM_VISTA_EXTRA_LARGE_ICONS Image 38Image 39
XLVM_VISTA_MEDIUM_ICONS Image 40Image 41
XLVM_VISTA_LARGE_ICONS Image 42Image 43
XLVM_VISTA_SMALL_ICONS Image 44Image 45
XLVM_VISTA_LIST Image 46Image 47

IMPLEMENTATION NOTE

Except for XXXX_DO_NOT_PERSIST and XXXX_UNDEFINED, the above symbols are #define'd as the actual list view commands sent via WM_COMMAND message.


CXFolderDialog API

Here are functions provided by CXFolderDialog:

FunctionDescription
enum XFILEDIALOG_OS_VERSION void EnableRegistry(BOOL bEnable) Enables/disables use of registry to store view mode
enum XFILEDIALOG_OS_VERSION GetOsVersion() Gets OS version used for folder select dialog
CString GetPath() Gets path of selected folder
int GetViewMode() Gets last-used view mode from folder select dialog
void SetOsVersion(enum XFILEDIALOG_OS_VERSION eOsVersion) Allows you to choose between old-style and Explorer-style dialog
void SetTitle(LPCTSTR lpszTitle) Sets title of folder select dialog
void SetViewMode(int cmd) Sets view mode for folder select dialog list control

How to use

To integrate CXFolderDialog into your app, you first need to add following files to your project:

  • XFolderDialog.cpp
  • XFolderDialog.h
  • XFileOpenListView.cpp
  • XFileOpenListView.h
  • XFolderDialog.rc
  • XFolderDialogRes.h
  • XHistoryCombo.cpp
  • XHistoryCombo.h
  • XWinVer.cpp
  • XWinVer.h

You also need to add XFolderDialog.rc to project rc file:

screenshot For Visual Studio 6 - go to View | Resource Includes... and in bottom listbox, scroll down to end. Insert #include "XFolderDialog.rc" right before #endif:

screenshot

screenshot For Visual Studio 2005 - right-click .rc file in Resource View, then choose Resource Includes... from shortcut menu:

screenshot

In bottom listbox, scroll down to end. Insert #include "XFolderDialog.rc" right before #endif:

screenshot

Next, include header file XFolderDialog.h in appropriate project files. Now you are ready to start using CXFolderDialog.

The demo app shows how to call XFolderDialog:

CXFolderDialog dlg(m_strInitialFolder);
dlg.SetOsVersion((enum CXFolderDialog::XFILEDIALOG_OS_VERSION) m_nOsVersion);
dlg.SetTitle(_T("Select Folder"));  // defaults to "Select Folder"
if (dlg.DoModal() == IDOK)
{
    CString strPath = dlg.GetPath();
    .
    .
    .

A Note on _WIN32_WINNT

The preprocessor symbol _WIN32_WINNT is used in commdlg.h in OPENFILENAME struct to configure its size. When _WIN32_WINNT is equal to or greater than 0x500, an additional three items are included in struct. The struct size (stored in struct member lStructSize) is how ::GetOpenFileName() determines which dialog to display - the old-style or Explorer-style dialog.

When XFolderDialog is displayed using XFILEDIALOG_AUTO_DETECT_OS_VERSION, the Explorer-style dialog will always be displayed on Windows 2000 (or later) systems. You can overrride this behavior by using XFILEDIALOG_OS_VERSION_4. Again, this override is accomplished by tweaking size of the OPENFILENAME struct.

Here is code that does this:

#if (_WIN32_WINNT >= 0x0500)

    #pragma message(__FILE__ "(" makestring(__LINE__) \
        ") : OPENFILENAME is large size (3 extra items are included)")

    if (IsWin2000())
        m_ofnEx.lStructSize = sizeof(OPENFILENAME);           // OS >= 2000, force to large size
    else
        m_ofnEx.lStructSize = OPENFILENAME_SIZE_VERSION_400;  // use small size

#else    // _WIN32_WINNT < 0x0500, or isn't defined

    #pragma message(__FILE__ "(" makestring(__LINE__) \
        ") : OPENFILENAME is small size (3 extra items are NOT included)")

    if (IsWin2000())
        m_ofnEx.lStructSize = sizeof(OPENFILENAMEEX);         // OS >= 2000, force to large size
    else
        m_ofnEx.lStructSize = OPENFILENAME_SIZE_VERSION_400;  // use small size

#endif

OPENFILENAME struct

typedef struct tagOFNA {
   DWORD        lStructSize;
   HWND         hwndOwner;
   HINSTANCE    hInstance;
   LPCSTR       lpstrFilter;
   LPSTR        lpstrCustomFilter;
   DWORD        nMaxCustFilter;
   DWORD        nFilterIndex;
   LPSTR        lpstrFile;
   DWORD        nMaxFile;
   LPSTR        lpstrFileTitle;
   DWORD        nMaxFileTitle;
   LPCSTR       lpstrInitialDir;
   LPCSTR       lpstrTitle;
   DWORD        Flags;
   WORD         nFileOffset;
   WORD         nFileExtension;
   LPCSTR       lpstrDefExt;
   LPARAM       lCustData;
   LPOFNHOOKPROC lpfnHook;
   LPCSTR       lpTemplateName;
#ifdef _MAC
   LPEDITMENU   lpEditInfo;
   LPCSTR       lpstrPrompt;
#endif
#if (_WIN32_WINNT >= 0x0500)
   void *		pvReserved;
   DWORD        dwReserved;
   DWORD        FlagsEx;
#endif // (_WIN32_WINNT >= 0x0500)
} OPENFILENAMEA, *LPOPENFILENAMEA;

Using Visual Studio 6, normal situation is that _WIN32_WINNT will not be defined, as you can see from message displayed in IDE output window:

Compiling...
XFolderDialog.cpp
...\src\XFolderDialog.cpp(68) : _WIN32_WINNT is not defined
...\src\XFolderDialog.cpp(290) : OPENFILENAME is small size (3 extra items are NOT included)

In Visual Studio 2005, _WIN32_WINNT is defined:

Compiling...
XFolderDialog.cpp
...\src\XFolderDialog.cpp(66) : _WIN32_WINNT = 0x0500
...\src\XFolderDialog.cpp(280) : OPENFILENAME is large size (3 extra items are included)

Acknowledgments

Revision History

Version 1.4 - 2010 June 2

  • Renamed Winver.* to XWinVer.* to avoid name conflict.
  • Fixed problem when running on Win7.

Version 1.3 - 2008 February 22

  • Fixed problems related to compiling under recent versions of VS.
  • Fixed bug when new folder is created and OK pressed, reported by McLyndon and Super Garrison.
  • Fixed bug when new path entered in mru combo, reported by Brad Bruce, with fix suggested by Manfred Drasch.
  • Fixed bug when used in dll, reported by k-mommos.
  • Fixed bug where you click My Computer then select folder, with fix suggested by Wade Ledbetter.
  • Added ability to set/save list view mode, requested by Aetschmaen.
  • Added demo project for VS2005.

Version 1.2 - 2005 March 22

  • Fixed problem with initial sizing of placebar, reported by XXX.

Version 1.1 - 2005 March 17

  • Improved performance by using file filter.
  • Changed screenshot paths to use forward slash.

Version 1.0 - 2005 March 15

  • Initial public release

Usage

This software is released under the Code Project Open License (CPOL). You are free to use this software in any way you like, except that you may not sell this source code. This software is provided "as is" with no expressed or implied warranty. I accept no liability for any damage or loss of business that this software may cause.

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) Hans Dietrich Software
United States United States
I attended St. Michael's College of the University of Toronto, with the intention of becoming a priest. A friend in the University's Computer Science Department got me interested in programming, and I have been hooked ever since.

Recently, I have moved to Los Angeles where I am doing consulting and development work.

For consulting and custom software development, please see www.hdsoft.org.






Comments and Discussions

 
GeneralMy vote of 5 Pin
Michael Haephrati22-Sep-12 5:20
professionalMichael Haephrati22-Sep-12 5:20 
AnswerVS2010 C3861 error after Windows Update Pin
Hans Dietrich2-May-11 6:54
mentorHans Dietrich2-May-11 6:54 
GeneralRe: VS2010 C3861 error after Windows Update Pin
RedDk2-May-11 7:48
RedDk2-May-11 7:48 
AnswerRe: VS2010 C3861 error after Windows Update Pin
Hans Dietrich2-May-11 8:21
mentorHans Dietrich2-May-11 8:21 
GeneralRe: VS2010 C3861 error after Windows Update Pin
RedDk2-May-11 8:42
RedDk2-May-11 8:42 
GeneralVS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
RedDk28-Apr-11 10:15
RedDk28-Apr-11 10:15 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich28-Apr-11 10:41
mentorHans Dietrich28-Apr-11 10:41 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
RedDk29-Apr-11 7:27
RedDk29-Apr-11 7:27 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
jymMCK29-Apr-11 8:57
jymMCK29-Apr-11 8:57 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich29-Apr-11 12:34
mentorHans Dietrich29-Apr-11 12:34 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich29-Apr-11 12:32
mentorHans Dietrich29-Apr-11 12:32 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
jymMCK2-May-11 3:07
jymMCK2-May-11 3:07 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
SaintNeil2-May-11 5:49
SaintNeil2-May-11 5:49 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich2-May-11 6:25
mentorHans Dietrich2-May-11 6:25 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
SaintNeil2-May-11 6:44
SaintNeil2-May-11 6:44 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich2-May-11 6:59
mentorHans Dietrich2-May-11 6:59 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
SaintNeil2-May-11 9:10
SaintNeil2-May-11 9:10 
AnswerRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich2-May-11 9:20
mentorHans Dietrich2-May-11 9:20 
GeneralRe: VS2010 issue, all projects in download, and in aside "XBrowseForFolder" ... C3861: 'AtlLoadSystemLibraryUsingFullPath' Pin
Hans Dietrich2-May-11 6:36
mentorHans Dietrich2-May-11 6:36 
GeneralThe OK button could never get tab stop on XP. Pin
rickju16-Mar-11 0:20
rickju16-Mar-11 0:20 
General"Look in" always defaults to the Documents library on Windows 7 Pin
B4oris20-Feb-11 16:31
B4oris20-Feb-11 16:31 
GeneralIt's very useful, but does not work for OFN_NOCHANGEDIR Pin
fangzj9-Jan-11 1:49
fangzj9-Jan-11 1:49 
GeneralRe: It's very useful, but does not work for OFN_NOCHANGEDIR Pin
phata23-Jul-13 5:34
phata23-Jul-13 5:34 
GeneralDemo project crashed on Window 7 Pin
ashukasama27-Dec-10 23:56
ashukasama27-Dec-10 23:56 
GeneralRe: Demo project crashed on Window 7 Pin
Hans Dietrich1-Jan-11 7:14
mentorHans Dietrich1-Jan-11 7:14 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.