Introduction
The included source files will allow you to use the Office 2000 and VS.NET style file dialogs in your applications, which will appear on all versions of Windows 95/98/NT/Me, as well as 2000. To use the dialog, simply add the source files to your project and use the standard CFileDialog
calling functions to show / manipulate it.
- Quick Guide
- Using it in Your App
- The Resource Script
- Handling Multiple File Types
- Layout / Size / Enabling Resizing
- Context Help
- Preview Panel
- Using the VS.NET style
- Common Questions
- Credits
- License
- Update History
Quick Guide
For example, to load the dialog with an "Open" button, use the code below
BXFileDialog dlg(TRUE);
dlg.m_ofn.lpstrTitle = "Open Document";
dlg.DoModal();
To show the save button, use FALSE
instead of TRUE
when creating the dialog:
BXFileDialog dlg(FALSE);
dlg.m_ofn.lpstrTitle = "Save Document";
dlg.DoModal();
To show the bitmap preview panel, pass TRUE
as the second parameter to the constructor:
BXFileDialog dlg(FALSE, TRUE);
dlg.m_ofn.lpstrTitle = "Save Document";
dlg.DoModal();
To allow the dialog to be resized, pass TRUE
as the third parameter to the constructor:
BXFileDialog dlg(TRUE, FALSE, TRUE);
dlg.m_ofn.lpstrTitle = "Open Document";
dlg.DoModal();
To set up file type filters, add this before your call to DoModal()
(this is optional):
CString szFilter = "HTML Documents (.Htm;.Html)|*.Htm;*.Html|";
szFilter += "Active Server Pages (.Asp)|*.Asp|";
szFilter += "Text Files (.Txt)|*.Txt|";
szFilter += "All Supported Files (.Htm;.Html;.Asp;.Txt;)"
"|*.Htm;*.Html;*.Asp;*.Txt;|";
szFilter += "All Files (*.*)|*.*|";
LPTSTR pch = szFilter.GetBuffer(0);
while ((pch = _tcschr(pch, '|')) != NULL)
*pch++ = '\0';
dlg.m_ofn.lpstrFilter = szFilter;
Using it in Your App
Below I will attempt to explain using it instead of the default file 'open' / 'save as' dialogs. I will use a method that in my opinion is easier than using multiple versions of the same code for each of your documents' Open and Save As commands. To do this, define (public
) and add the following function to your CWinApp
derived class (make sure you include the dialog header in this file).
BOOL CMyApp::DoPromptFileName(CString &fileName, UINT nIDSTitle,
DWORD lFlags, BOOL bOpen, BOOL bPreview, BOOL bSizing)
{
BXFileDialog dlg(bOpen, bPreview, bSizing);
CString szFilter = ".HTML Documents (.Htm;.Html)|*.Htm;*.Html|";
szFilter += "Active Server Pages (.Asp)|*.Asp|";
szFilter += "Text Files (.Txt)|*.Txt|";
szFilter += "All Supported Files (.Htm;.Html;.Asp;.Txt;)"
"|*.Htm;*.Html;*.Asp;*.Txt;|";
szFilter += "All Files (*.*)|*.*|";
LPTSTR pch = szFilter.GetBuffer(0);
while ((pch = _tcschr(pch, '|')) != NULL)
*pch++ = '\0';
CString strTitle;
strTitle.LoadString(nIDSTitle);
dlg.m_ofn.lpstrFilter = szFilter ;
dlg.m_ofn.lpstrTitle = strTitle;
dlg.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);
dlg.m_ofn.hwndOwner = AfxGetMainWnd()->m_hWnd;
if (dlg.DoModal() == IDOK)
return TRUE;
return FALSE;
}
Also make sure that in your app header, theApp
is defined, to make it easier to access your class. Eg:
extern CMyApp theApp;
Now open your document source file. Make sure it includes the main app header (so you can use theApp
), and unless you already have an override for OnOpenDocument(...)
, use the class wizard to insert one for you. Then modify as follows (IDS_FILE_OPEN
is a string ID for the dialog title):
BOOL CMyDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!theApp.DoPromptFileName(lpszPathName, IDS_FILE_OPEN,
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, TRUE, FALSE, TRUE))
return FALSE;
return TRUE;
}
The override the documents' OnSaveDocument(...)
function, as follows (again, IDS_FILE_SAVEAS
is a string ID for the dialog title):
BOOL CMyDoc::OnSaveDocument(LPCTSTR lpszPathName)
{
if (!theApp.DoPromptFileName(lpszPathName, IDS_FILE_SAVEAS,
OFN_HIDEREADONLY | OFN_FILEMUSTEXIST, FALSE, FALSE, TRUE))
return FALSE;
return TRUE;
}
That is all you need to add. If you have more than one CDocument
derived class, simply repeat as necessary.
Handling Multiple File Types
If you want to display different commands in the OK button's drop-down menu, you can override the virtual void OnFileTypeChange(DWORD dwNewFilterIndex)
function. This function is called whenever the user selects a new file type from the 'File Type' combo box. The dwNewFilterIndex parameter contains the index of the new file type in the array passed to the dialog in the OPENFILENAME
structure you pass to the dialog before showing it. You can switch on this DWORD to load different commands depending on the file type, e.g.:
m_btn.m_menu.DestroyMenu();
m_btn.m_menu.CreatePopupMenu();
switch(dwNewFilterIndex)
{
case 0:
m_btn.AddMenuItem(ID_START,"&Open",0);
m_btn.AddMenuItem(ID_START+1,"Open with &Filter",0);
break;
case 1:
m_btn.AddMenuItem(ID_START,"&Open",0);
case 2:
m_btn.AddMenuItem(ID_START,"&Open",0);
m_btn.AddMenuItem(ID_START+1,"Open As &HTML",0);
default:
break;
}
The Resource Script
In order to make including the dialog in your existing projects as simple as possible, you will no longer need to copy the individual resources to your own project's resource file. To use the resources, follow these steps:
- Select the ResourceView pane in Developer Studio (the VC++ IDE).
- Select the resource script used by your project.
- Select View | Resource Includes... from the menu.
- In the 'Compile-time directives' edit box, add the line
#include "cmn.rc"
before the final #endif
statement.
- Press OK and accept the changes.
You have just told the resource compiler to compile the separate resource script (named cmn.rc) when it compiles your project. The header defining the ID's in this script will automatically be made available to you.
Layout / Size
By default the initial size of the dialog will be that of the static control in the dialog template called IDC_SIZE_TEMPLATE
. Changing this size will cause the dialog and all it's controls to be resized too. The width of the grey static control is used to calculate the width of the 'side bar'.
You can change the #define CONTROL_GAP
to change the default spacing between controls used when updating the dialog's layout. Microsoft Office uses a value of 3. The default for this code is 5, as it looks better (in my opinion).
Sizing Support
On Windows 98 and NT 5 and later, the default Windows file dialogs can be resized. To enable this dialog to be resized in this way, pass TRUE (or FALSE to disable it) as the third parameter to the dialog constructor. For an example, see the Quick Guide section above.
Context Help
By default, Windows can't display context help for the custom controls we add to the dialog (in this case the 'side bar'), as it is not meant to be there. In order to be able to display context help for the buttons in this bar (and to override any of the default controls), simple make sure you have the HtmlHelp header and library files in your projects include path (freely available from Microsoft - search for HtmlHelp Workshop on MSDN) and compile your project with _USE_HTMLHELP
defined.
The strings used to display the text in the context help windows is obtained from the string resource in cmn.rc.
Refer to the source to see how the DoPopupHelp()
function is implemented. Feel free to use this function elsewhere in your projects, without credit.
Preview Panel
You can now optionally display a 'preview panel' to the right of the listbox, in the same fashion as Office 2000 does. To show this panel, pass TRUE as the second parameter in the creation statement (shown in the examples above).
This preview panel will display any images that your system will, using the IPicture interface.
Visual Studio.NET style
You can now make the sidebar buttons appear in the new VS.NET style (see screenshot at the top of this page). To do this, simply call SetAppearance(...) before calling DoModal(), and pass in APPEARANCE_VSDOTNET. E.g.:
BXFileDialog dlg();
dlg.SetAppearance(BXFileDialog::eAppearance::APPEARANCE_VSDOTNET);
dlg.DoModal();
Possible values to pass to SetAppearance(...) are:
APPEARANCE_DEFAULT
APPEARANCE_VSDOTNET
Common Questions
Why can't I compile the project?
There can be many reasons for your project not compiling, but the most common related to the use of this dialog are:
- You do not have the HtmlHelp SDK installed on your machine, and have not undefined
_USE_HTMLHELP
in the project settings.
- You have not set up the paths in Devloper Studio correctly, if you do have the HtmlHelp SDK installed.
- OLE containment support must be enabled for your project, and you have not enabled it. Call
AfxEnableControlContainer()
from your CWinApp::InitInstance()
function.
Why isn't the new dialog showing instead of the old one?
You have to override the OnSaveDocument()
function for each of your document types, and OnFileOpen()
in your main CWinApp
derived class, and use the new dialog in place of the old one. See the Using it in Your App section above for an example.
Credits
Based on the original code by Norm Almond. Maintained by David Wulff. Contains some code by Joel Bernard, Anatoly Danekin, Wes Rogers, Tak^Shoran and Chris Maunder.
And a special thank you to all of you who have posted bug reports and/or fixes, or have simply said "Hey, this would be cool...".
License
This code is provided on an "AS-IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. You can use the code and any segments hereof, in any product, commercial or otherwise, provided that any copyright information contained in the source files remains unaltered and intact. If you contribute to the source in any way, regardless of whether you release said changes, you must comment them and identify them as your own to prevent confusion as to the author of said changes. Use of this code in any application gives me marital rights to your first-born daughter. (Okay, maybe not that last sentence...)
I would appreciate a quick email [dwulff@battleaxesoftware.com] if you are going to use the code in a commercial application, purely out of interest. You are NOT required to do this, nor are you required to credit the original authors in your application or its documentation.
Update History
- Previous Update History
- 22 March 2001 - David Wulff - Updated the source to include the VS.NET style for the sidebar. Cleaned up some minor problems with the picture preview not updating if the dialog was dragged off screen (thanks to James Millson for bringing it to my attention). Added a new demo program to show off the VS.NET style dialogs. I added basic support for opening files from the Internet (by downloading them to the temp directory). This code uses Chris Maunder's CWebGrab class, and my implementation of it is still in testing and has only been used to download text files so far.
- 24 Mar 2001 - Tak^Shoran, working sizing support for dialogs with no image preview.
- 31 Mar 2001 - David Wulff, Major Update. A lot of the code has been updated, and the source files have been tidied up and re-commented. The sizing support now works for both preview-enabled and normal dialogs (Windows 98 and 2000 and later only). Sizing support and the new VS.NET style can now be dynamically specified rather than at compile time. Article content updated to reflect new code.
- 5 Aug 2001 - David Wulff, now when you select a non-image file, or a folder, the preview pane is cleared. Added a handler for the
CDN_TYPECHANGE
message, so you can customise the OK button's drop-down menu. Article content updated to reflect new code. The debug build of the sample program will now
- 19 October 2003 - David Wulff - Updated the source to support Windows XP (which uses a combobox instead of an edit control for the file name).
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.