Creating an Open/SaveAs That Stores the MRUD

Environment: MFC4.2; sample written in MSVC++5.0 on Win98

The Problem

Basically, I got sick of having to navigate from "MyDocuments" every time I opened an app. One of my projects requires several instances to be open simultaneously and the extra folder-hopping just got to me.

The Solution

I created a class to replace the existing CDocManager class in my MFC Doc/View projects. The new class, CRegDocMgr (based on CDocManager), stores the most recently used directory (MRUD) in the Registry—in HKEY_CURRENT_USER, along with any other information normally stored there by the MFC framework. It adds the string "MRUD" to the "Settings" key. So the whole path would be HKEY_CURRENT_USER/MyCompany/MyApp/Settings/MRUD.

How It Works

The new doc manager replaces the original in the app's InitInstance function—AFTER specifying standard Registry settings, but BEFORE the app registers its document templates. The constructor of CRegDocMgr pulls the MRUD from the Registry and keeps it in the CString m_strInitialMRUD. Each time a file is saved or opened (including MRU/drag-and-drop files), m_strMRUD (which was initialized to m_strInitialMRUD) is updated. When the destructor for CRegDocMgr is called just before the program closes, it writes m_strMRUD to the Registry, if it differs from m_strInitialMRUD (avoiding unnecessary Registry access).

How To Use It

Only two lines beyond the normal inclusion of a class are needed for basic usage. First, as is usual, add CRegDocMgr.cpp and CRegDocMgr.h to your project. In the main app implementation file (MyApp.cpp), be sure to #include "RegDocMgr.h". Then, in the InitInstance function for the app, add two lines AFTER the Registry init code, but BEFORE any document templates are registered.

MyApp.cpp : Defines the class behaviors for the application.
#include "RegDocMgr.h"

... standard InitInstance stuff ...
SetRegistryKey(_T("Your Company Name"));
// Load standard INI file options (including MRU)

  ASSERT(m_pDocManager == NULL);
  m_pDocManager = new CRegDocMgr;

... and the rest continues ...
// Register document templates
CSingleDocTemplate* pDocTemplate;

"That's all there is to it." The Open and SaveAs file dialogs will behave exactly the same as before (including IDR_MAINFRAME filters), except that they will start in the MRUD.

Extended Functions

The class also allows you to access the MRUD from elsewhere in your program. This is useful if you have import or export functions in your app that could benefit from MRUD access. You have access to the MRUD initially loaded from the Registry (CString CRegDocMgr::GetInitialMRUD()) and to the current MRUD (CString CRegDocMgr::GetCurrentMRUD()). You may also set the MRUD by passing it a complete filename (CString CRegDocMgr::SetMRUD(CString csFileName)). The class will extract the path and set it as the MRUD.

To use these functions in an import/export, add CRegDocMgr to your app as noted above; then, in the import/export sections of your code, add a few more lines to access the MRUD before showing your import/export file dialog. Afterward, you may also set the MRUD to reflect the import/export directory used, if you so choose.

// MyAppView.cpp : implementation of the MyAppView class
#include "RegDocMgr.h"

void MyAppView::OnExport() 
  // setup for the EXPORT file dialog

  // for a probable title
  MyAppDoc* pDoc = GetDocument();
  CString csTitle = pDoc->GetTitle();
  if (csTitle != "Untitled")
    csTitle = csTitle.Left(csTitle.GetLength() - 4);

  // file filters
  static char szFilter[] = "ABC Files 
         (*.abc)|*.abc; *.abc|All Files (*.*)|*.*||";

  // create the dialog
  CFileDialog dlgExport(false, "abc", (LPCTSTR) csTitle,
      szFilter, AfxGetMainWnd());
  dlgExport.m_ofn.lpstrTitle = "Export to file"; // window title

  // IMPORT setup
  // static char szFilter[] = "ABC Files (*.abc)|*.abc; *.abc||";
  // CFileDialog dlgImport(true, "abc", NULL, // no preset filename
  //      szFilter, AfxGetMainWnd());

  // set a starting directory if one exists
  CRegDocMgr* pDocMgr = (CRegDocMgr*) AfxGetApp()->m_pDocManager;
  dlgExport.m_ofn.lpstrInitialDir = pDocMgr->GetCurrentMRUD();

  // show the file dialog
  if (dlgExport.DoModal() == IDOK)
    // omit this if import/export should not affect document MRUD

    //... proceed with the import/export ... etc


The project includes a small text file named "". Copy/Move it to wherever you'd like to test the app—open the app, open the file, close the app, re-open the app, and go to File/Open. The dialog should start in the directory from which you last loaded "". There is also an "Export" option on the File menu. It will create a meaningless text file, but you should be able to see that it opens to the MRUD and updates the MRUD, should you save the exported file.

Why It Works

CRegDocMgr is 99% CDocManager. Only two virtual functions, "DoPromptFileName" and "OpenDocumentFile", have been modified from the original MFC code. DoPromptFileName is called whenever the file dialog is opened for Open/SaveAs and OpenDocumentFile is used to catch MRU files opened from the menu bar and when files are dropped on the app.


You can remove the "All Files (*.*)" filter from your file dialogs if you define _HIDEALLFILTER. The class then skips that extra section of code which adds *.* to the filters.

The Registry accesses have all been made unicode-safe using the _T macro, to match the rest of the MFC unicode-enabled code.

I included options for _MAC, but have no way to test them.

The AppendFilterSuffix function refused to behave unless I included it in RegDocMgr.cpp too.


Thanks to Jorge Lodos, whose article "Changing the default file open/save dialogs in an MFC doc/view application" pointed me in the right direction.


Download demo project - 21 Kb
Download demo EXE - 8 Kb
Download source - 6 Kb


  • Thanks, I like this.

    Posted by Legacy on 09/06/2002 12:00am

    Originally posted by: Bill Dickinson

    Thanks, I like this, but have been too lazy to do it.

  • Good Work!

    Posted by Legacy on 08/29/2002 12:00am

    Originally posted by: DaFu Chen

    Good Work, This feature simplifies the operation

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

Top White Papers and Webcasts

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

  • Protecting business operations means shifting the priorities around availability from disaster recovery to business continuity. Enterprises are shifting their focus from recovery from a disaster to preventing the disaster in the first place. With this change in mindset, disaster recovery is no longer the first line of defense; the organizations with a smarter business continuity practice are less impacted when disasters strike. This SmartSelect will provide insight to help guide your enterprise toward better …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds