Virtual Developer Workshop: Containerized Development with Docker

Before I tell you how to change the default behaviour, lets understand how MFC displays the file open and file save dialogs.
When you select the menu File Open, the command message is routed to CWinApp::OnFileOpen, which calls CDocManager::OnFileOpen through its member m_pDocManager (a pointer to a CDocManager object). This last function calls the CDocManager virtual member DoPromptFileName, and on success calls CWinApp::OpenDocumentFile, with the selected document path. The file open dialog is displayed in the DoPromptFileName virtual function.
When saving, the File Save (or Save As) command message is routed to the CDocument::OnFileSave (or CDocument::OnFileSaveAs). In boths cases the CDocument::DoSave function gets called, either with a file name (we are saving an opened document) or NULL parameter (new document or saving as). At last, if the file name is NULL, CDocument::DoSave calls CWinApp::DoPromptFileName, that validates the m_pDocManager member and calls CDocManager::DoPromptFileName to display the Save As dialog.
As we see, the CDocManager::DoPromptFileName function (which is virtual!) is responsible for displaying the standard open and save dialogs (a boolean parameter decides which one).

It seems trivial now, that to change default behaviour, you have to override the DoPromptFileName function in the CDocManager class, and somehow tell the application class to use your own modified CDocManager, instead of the original class. Below is the code for a custom CDocManager that displays a dialog descending from CFileDialog:

// CDocManager class declaration

class CDocManagerEx : public CDocManager

// Construction

// Attributes

// Operations

// Overrides
	// helper for standard commdlg dialogs
	virtual BOOL DoPromptFileName(CString& fileName, UINT nIDSTitle,
			DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate);

// Implementation
	virtual ~CDocManagerEx();

// DocManager.cpp : implementation file

#include "stdafx.h"
#include "PreviewFileDlg.h"
#include "DocManager.h" // the header with the class declaration

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;

static void AppendFilterSuffix(CString& filter, OPENFILENAME& ofn,
	CDocTemplate* pTemplate, CString* pstrDefaultExt)
	ASSERT_KINDOF(CDocTemplate, pTemplate);

	CString strFilterExt, strFilterName;
	if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
	 !strFilterExt.IsEmpty() &&
	 pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
		// a file based document template - add to filter list
#ifndef _MAC
		ASSERT(strFilterExt[0] == '.');
		if (pstrDefaultExt != NULL)
			// set the default extension
#ifndef _MAC
			*pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1;  // skip the '.'
			*pstrDefaultExt = strFilterExt;
			ofn.lpstrDefExt = (LPTSTR)(LPCTSTR)(*pstrDefaultExt);
			ofn.nFilterIndex = ofn.nMaxCustFilter + 1;  // 1 based number

		// add to filter
		filter += strFilterName;
		ASSERT(!filter.IsEmpty());  // must have a file type name
		filter += (TCHAR)'\0';  // next string please
#ifndef _MAC
		filter += (TCHAR)'*';
		filter += strFilterExt;
		filter += (TCHAR)'\0';  // next string please

// CDocManagerEx




BOOL CDocManagerEx::DoPromptFileName(CString& fileName, UINT nIDSTitle, DWORD lFlags, BOOL bOpenFileDialog, CDocTemplate* pTemplate)
	CPreviewFileDlg dlgFile(bOpenFileDialog); // this is the only modified line! 

	CString title;

	dlgFile.m_ofn.Flags |= lFlags;

	CString strFilter;
	CString strDefault;
	if (pTemplate != NULL)
		AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault);
		// do for all doc template
		POSITION pos = m_templateList.GetHeadPosition();
		BOOL bFirst = TRUE;
		while (pos != NULL)
			CDocTemplate* pTemplate = (CDocTemplate*)m_templateList.GetNext(pos);
			AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate,
				bFirst ? &strDefault : NULL);
			bFirst = FALSE;

	// append the "*.*" all files filter
	CString allFilter;
	strFilter += allFilter;
	strFilter += (TCHAR)'\0';   // next string please
#ifndef _MAC
	strFilter += _T("*.*");
	strFilter += _T("****");
	strFilter += (TCHAR)'\0';   // last string

	dlgFile.m_ofn.lpstrFilter = strFilter;
#ifndef _MAC
	dlgFile.m_ofn.lpstrTitle = title;
	dlgFile.m_ofn.lpstrPrompt = title;
	dlgFile.m_ofn.lpstrFile = fileName.GetBuffer(_MAX_PATH);

	BOOL bResult = dlgFile.DoModal() == IDOK ? TRUE : FALSE;
	return bResult;

The code was borrowed completely from original MFC sources, only one line had to be modified: the dialog declaration (of course, this is because the example dialog is a CFileDialog descendant, otherwise you would have to make some more modifications). For a standard dialog with preview look in the dialogs section.
The AppendFilterSuffix function was called from our DoPromptFileName function and was copied verbatim from the MFC sources.
The only thing that remains to be said about this class is that if you want to use different dialogs for opening and saving, then you can do so using the bOpenFileDialog parameter, which is TRUE when opening and FALSE otherwise.

We still have to make our application class to use the new CDocManagerEx, instead of the default CDocManager. The CWinApp uses the document manager through its m_pDocManager member, so all we have to do is initializate this member correctly. A closer look to the MFC code shows that CWinApp creates the object to which this member points only in the CWinApp::AddDocTemplate, a function that normally is called only in our override of the CWinApp::InitInstance function. The CWinApp::AddDocTemplate function only creates the CDocManager object if the m_pDocManager member is NULL, thus once the m_pDocManager pointer is correctly initialized, the CWinApp::AddDocTemplate function can be safely called.
So, the final step is to initialize the m_pDocManager member in our InitInstance override before we call CWinApp::AddDocTemplate (you can choose not to call CWinApp::AddDocTemplate at all and call directly m_pDocManager->AddDocTemplate).
Here is the code to do that:

BOOL COurApp::InitInstance()
	// Standard initialization
	// If you are not using these features and wish to reduce the size
	//  of your final executable, you should remove from the following
	//  the specific initialization routines you do not need.

#ifdef _AFXDLL
	Enable3dControls();			// Call this when using MFC in a shared DLL
	Enable3dControlsStatic();	// Call this when linking to MFC statically

	// Change the registry key under which our settings are stored.
	// You should modify this string to be something appropriate
	// such as the name of your company or organization.
	SetRegistryKey(_T("Local AppWizard-Generated Applications"));

	LoadStdProfileSettings();  // Load standard INI file options (including MRU)

	// Register the application's document templates.  Document templates
	//  serve as the connection between documents, frame windows and views.

	CMultiDocTemplate* pDocTemplate;
	pDocTemplate = new CMultiDocTemplate(
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
	ASSERT(m_pDocManager == NULL);
	m_pDocManager = new CDocManagerEx;
	m_pDocManager->AddDocTemplate(pDocTemplate); // or just AddDocTemplate(pDocTemplate);
	// create main MDI Frame window
	CMainFrame* pMainFrame = new CMainFrame;
	if (!pMainFrame->LoadFrame(IDR_MAINFRAME))
		return FALSE;
	m_pMainWnd = pMainFrame;

	// Enable drag/drop open

	// Enable DDE Execute open

	// Parse command line for standard shell commands, DDE, file open
	CCommandLineInfo cmdInfo;

	// Dispatch commands specified on the command line
	if (!ProcessShellCommand(cmdInfo))
		return FALSE;

	// The main window has been initialized, so show and update it.

	return TRUE;

It was all we needed to change the default file open and file save dialogs. In the samples section you can find an enhanced DIBLOOK sample that uses this technique to show standard file dialogs with preview.

Last updated: 25 June 1998


  • Test, just a test

    Posted by XRumerTest on 05/09/2017 04:35am

    Hello. And Bye.

  • save the file in driver

    Posted by elaangovan on 07/09/2007 09:53am

    Hi, i want to save the file in any driver via visual basic.

  • Tricky problem w/ this. Can someone help?

    Posted by Legacy on 03/14/2003 08:00am

    Originally posted by: Per

    This article is great, but i'm having a little problem. When i call the line

    m_pDocManager = new CDocManagerEx;

    m_pDocManager remains NULL, and in AddDocTemplate() my derived CWinApp creates a "new CDocManager" that it uses instead of my overloaded class.

    Has anyone seen this behavior before? My code is pretty much cut-and-paste from the article to see if it worked.

  • How to customize the CFileDialog ?

    Posted by Legacy on 12/05/2001 08:00am

    Originally posted by: jerry

    I want to display the files in selected folder as a sorted order in the MFC file open dialog box. Is it possible ? ie; any way to get the all files in the selected folder for customizing ? If possible help to do that..

    Thanks in Advance and Waiting your replay


  • Change Dialog

    Posted by Legacy on 07/13/2001 07:00am

    Originally posted by: Nagesh

    I want to know , is it possible to show the dialog withhout file open or save functionality. I mean that if the dialog class is inherited from CFileDialog class..but don't want the open file or save dialog, it should look as an general dialog as inherited from CDialog.
    If possible, Please let me know it.
    Waiting for your reply

  • You must have javascript enabled in order to post comments.

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

Most Popular Programming Stories

More for Developers

RSS Feeds

Thanks for your registration, follow us on our social networks to keep up-to-date