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:
When I looked at the dialog in Microsoft Word, I saw that my
Project Manager was right. This is what I found:
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 |
|
|
2000 |
|
|
XP |
|
|
Vista |
|
|
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:
Persistent List View Mode |
|
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:
-
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"));
- 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.
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:
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")); 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); else
m_ofnEx.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#else
#pragma message(__FILE__ "(" makestring(__LINE__) \
") : OPENFILENAME is small size (3 extra items are NOT included)")
if (IsWin2000())
m_ofnEx.lStructSize = sizeof(OPENFILENAMEEX); else
m_ofnEx.lStructSize = OPENFILENAME_SIZE_VERSION_400;
#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 } 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
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.