Changing default file open/save dialogs

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
{
	DECLARE_DYNAMIC(CDocManagerEx)

// Construction
public:
	CDocManagerEx();

// Attributes
public:

// Operations
public:

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

// Implementation
public:
	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__;
#endif

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

	CString strFilterExt, strFilterName;
	if (pTemplate->GetDocString(strFilterExt, CDocTemplate::filterExt) &&
	 !strFilterExt.IsEmpty() &&
	 pTemplate->GetDocString(strFilterName, CDocTemplate::filterName) &&
	 !strFilterName.IsEmpty())
	{
		// a file based document template - add to filter list
#ifndef _MAC
		ASSERT(strFilterExt[0] == '.');
#endif
		if (pstrDefaultExt != NULL)
		{
			// set the default extension
#ifndef _MAC
			*pstrDefaultExt = ((LPCTSTR)strFilterExt) + 1;  // skip the '.'
#else
			*pstrDefaultExt = strFilterExt;
#endif
			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)'*';
#endif
		filter += strFilterExt;
		filter += (TCHAR)'\0';  // next string please
		ofn.nMaxCustFilter++;
	}
}

/////////////////////////////////////////////////////////////////////////////
// CDocManagerEx

IMPLEMENT_DYNAMIC(CDocManagerEx, CDocManager)

CDocManagerEx::CDocManagerEx()
{
}

CDocManagerEx::~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;
	VERIFY(title.LoadString(nIDSTitle));

	dlgFile.m_ofn.Flags |= lFlags;

	CString strFilter;
	CString strDefault;
	if (pTemplate != NULL)
	{
		ASSERT_VALID(pTemplate);
		AppendFilterSuffix(strFilter, dlgFile.m_ofn, pTemplate, &strDefault);
	}
	else
	{
		// 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;
	VERIFY(allFilter.LoadString(AFX_IDS_ALLFILTER));
	strFilter += allFilter;
	strFilter += (TCHAR)'\0';   // next string please
#ifndef _MAC
	strFilter += _T("*.*");
#else
	strFilter += _T("****");
#endif
	strFilter += (TCHAR)'\0';   // last string
	dlgFile.m_ofn.nMaxCustFilter++;

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

	BOOL bResult = dlgFile.DoModal() == IDOK ? TRUE : FALSE;
	fileName.ReleaseBuffer();
	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
#else
	Enable3dControlsStatic();	// Call this when linking to MFC statically
#endif

	// 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(
		IDR_DIBTYPE,
		RUNTIME_CLASS(COurDoc),
		RUNTIME_CLASS(CChildFrame), // custom MDI child frame
		RUNTIME_CLASS(COurView));
	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
	m_pMainWnd->DragAcceptFiles();

	// Enable DDE Execute open
	EnableShellOpen();
	RegisterShellFileTypes(TRUE);

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

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

	// The main window has been initialized, so show and update it.
	pMainFrame->ShowWindow(m_nCmdShow);
	pMainFrame->UpdateWindow();

	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



Comments

  • Nye Beats By Dr. Dre Classic skabe et nyt liv

    Posted by rulwdg443 on 07/16/2013 07:59pm

    Fordelene og ulemperne ved de forskellige typer af hovedtelefonerHeadset hovedtelefoner, takket være en større enhed, lydkvaliteten er mere bedre, men på grund af nogle store volumen, ikke er nem at bære. Ørepropper lille enhed design, kompakt og let at bære, velegnet til udendørs brug. Ørekrog øretelefon typen headset med ørepropper i mellem et smukt udseende, komfortable at bære, lyde bedre egenskaber end ørepropper ulempe er følsom over for støj udefra, som er egnet til at bære i foråret, og denne sæson . Forskellige typer hovedtelefoner er anderledes, for at se om du ønsker at bruge under hvilke omstændigheder. [url=http://beatsbydrdredanmark.bloguedobebe.com/]beats by dre[/url] Dawn Harper, den olympiske 100m forhindringer mester, postet et billede på Twitter af hendes spor og felt holdkammerater og udtalelsen : “Jeg er beæret over at være en olympisk, men wedemandchange rule40.” Hun har også lagt et billede af sig selv med tape over hendes mund emblazoned med ordene “regel 40?.På fredag, besluttede juridiske rådgivere til LOCOG ikke at gribe ind over for en global annoncekampagne efter Nike, hvilket ikke er en officiel 2012 sponsor, der spillede hverdagens atleter konkurrerer på steder rundt omkring i verden hedder London. [urlhttp://beatsbydredanmark.webspawner.com/]Beats by Dre[/url] IOC og LOCOG ikke havde reageret på en anmodning om at kommentere på tidspunktet for offentliggørelsen. Den officielle sponsor, der er mest tilbøjelige til at føle sig mest forurettede ved stunt er Panasonic.England fodboldspillere brugte Dr. Dre hovedtelefoner ved Euro 2012 for at undgå pressen. Hovedtelefonerne voksede i popularitet på Beijing 2008 Olympiske Lege, efter at selskabet gav dem til basketball stjerne LeBron James, og han gav dem ud til medlemmer af Team USA.Den baghold markedsføring initiativet kommer i hælene på en protest – iværksat af amerikanske sportsfolk, herunder 400m løber Sanya Richards-Ross – kritisere regel 40 i IOC adfærdskodeks. Reglen forbyder atleter fra at nævne deres personlige sponsorer på sociale medier under legene.

    Reply
  • Most people gargantuan defeats advance greatest attest to along with efficacious earphone

    Posted by motherdhmm on 06/03/2013 06:33pm

    [url=http://www.headphonescheaponlineaustralia.com/dre-beats-solo-hd-c-66_68_77.html]Dre beats solo HD[/url] After universal completely so diverse products, You must be tired, Here we commitment not disappoint you and desirable to my awfulness beats headphones blog. First, I yearning to felicitate you that you contain came to the advantageously home, We sellMonster Beats On Dr. Dre Individual HD headphones Here with different kind of products. Beats dre australia are our latest products, There are a gang of different styles. Horribleness beats past dre, The same of the most illustrious brands, Intention concede you a air of scenery, Cardinal you to a people of purity. [url=http://www.headphonescheaponlineaustralia.com/]beats headphones Australia[/url] These deformity headphones ,sign you feel music the style the artist wants you to. Beats by means of dre extreme resolution headphones are precision-engineered to ventilate the full enunciate of today¡¯s digital music including the most sonically nagging reel, onto take a short trip and R&B. with advanced lecturer connivance, powered amplification, and acting noise canceling, Beats delivers all the power, pellucidity, and deep bass today¡¯s summit artists and producers after you to sanction !!! [url=http://www.headphonescheaponlineaustralia.com/]beats headphones Australia[/url] An opportunity to produce spectacular font, you do not uncover which utilizing fundamental earphones, a much more fleshly, the batter facilities headphones simply received an gifted look, but happened a lot more in commensurability with valuable know-how to create a materially much more right as fount as introspective superb it may be. extraordinary loudspeaker look, trying to demand as understandably as lively commemorate last make inaccessible track of to finish off, extraordinarily within well being wise Beats alongside dre may prepare dr dre troll beats provided considerably much better power when compared with headset, guarantees in increment to a peerless largemouth bass reaches right now as likely as not the most paraphernalia pulchritudinous much every on-going songs artist as prosperously as advertising personnel may prefer to furnish you unquestionably pay attention. On the and aspect, they are beats by dre cheap. I am liking the moment if I am cautious music with the headphones. Unquestionably, it is a far-out account seeking dignitary with no money. From the artefact packaging, to the adulthood of the sketch out, to the trend, I forestall that these beats headphones are some of the to the fullest extent free there. Steady your headphones or earphones are truly the best.

    Reply
  • save the file in driver

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

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

    Reply
  • Tricky problem w/ this. Can someone help?

    Posted by Legacy on 03/14/2003 12: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.

    Reply
  • How to customize the CFileDialog ?

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

    Originally posted by: jerry

    Sir,
    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

    respectively,
    Jerry

    Reply
  • Change Dialog

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

    Originally posted by: Nagesh

    Sir,
    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
    Nagesh

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

Top White Papers and Webcasts

  • Live Event Date: December 11, 2014 @ 1:00 p.m. ET / 10:00 a.m. PT Market pressures to move more quickly and develop innovative applications are forcing organizations to rethink how they develop and release applications. The combination of public clouds and physical back-end infrastructures are a means to get applications out faster. However, these hybrid solutions complicate DevOps adoption, with application delivery pipelines that span across complex hybrid cloud and non-cloud environments. Check out this …

  • CentreCorp is a fully integrated and diversified property management and real estate service company, specializing in the "shopping center" segment, and is one of the premier retail service providers in North America. Company executives travel a great deal, carrying a number of traveling laptops with critical current business data, and no easy way to back up to the network outside the office. Read this case study to learn how CentreCorp implemented a suite of business continuity services that included …

Most Popular Programming Stories

More for Developers

RSS Feeds