Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

XFolderDialog - a folder selection dialog based on CFileDialog

0.00/5 (No votes)
2 Jun 2010 1  
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 Mode XP Vista
XLVM_XP_DO_NOT_PERSIST
XLVM_XP_UNDEFINED
XLVM_XP_ICONS
XLVM_XP_LIST
XLVM_XP_DETAILS
XLVM_XP_THUMBNAILS
XLVM_XP_TILES
XLVM_VISTA_DO_NOT_PERSIST
XLVM_VISTA_UNDEFINED
XLVM_VISTA_DETAILS
XLVM_VISTA_TILES
XLVM_VISTA_EXTRA_LARGE_ICONS
XLVM_VISTA_MEDIUM_ICONS
XLVM_VISTA_LARGE_ICONS
XLVM_VISTA_SMALL_ICONS
XLVM_VISTA_LIST

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:

Function Description
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 has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here