[2 days left] What’s wrong with your cloud strategy? Learn why multicloud solutions matter with Nimble Storage.Register Now


How to find default directory from a CFileDialog

Posted on 2001-07-23
Medium Priority
Last Modified: 2013-11-20
I am trying to extract the initial directory so that the user can start from the folder that they chose last time. I use a CFileDialog to open the file and in Win98 it typically starts in "My Documents". If the user navigates somewhere else, then this folder is remembered for the duration of the session. I want to remember this so that I can set it at the start of the next session. I thought that in the WM_CLOSE of the CMainFrame class I could put the following:

    CFileDialog fd(TRUE);

    CString sFinalDir = fd.m_ofn.lpstrInitialDir;
    theApp.WriteProfileString(SETTINGS_KEY,               INITIALDIR_KEY, sFinalDir);

I could then do the following in the InitInstance of my app:

   // find initial directory, if any
    m_sInitialDir = GetProfileString(SETTINGS_KEY, INITIALDIR_KEY);

and stuff this into the m_ofn struct so that subsequent File Opens would start at the previous folder.

Unfortunately the m_ofn contains a null for the lpstrInitialDir when I do the WM_CLOSE. How can I get at the internal folder that CFileDialog is holding so that I can start there next time. Once I have this how can I ensure that this folder is the place to start next time. I was going to create a CFileDialog and then set the m_ofn.lpstrInitialDir member to the last directory that I can recover from the registry.

Question by:emitchell
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 2
  • +2

Expert Comment

ID: 6310750
  Try saving the initial directory immediately after the user closes the dialog box.  When the OK button is pressed, it seem like your waiting to long to get the data and it is no longer valid.

My 2 cents...
LVL 49

Expert Comment

ID: 6310893
Here is the basic technique:

When your program starts, use a command like:

  m_sOpenFileDir= theApp.GetProfileString("Prefs", "OpenFileDir", "c:\\My Documents");

Now, at some point, you will bring up the CFileDialog, as follows:

  CFileDialog dlg( TRUE );
  dlg.m_ofn.lpstrInitialDir=(LPCSTR) m_sOpenFileDir;
  int nRet= dlg.DoModal();
  if (nRet== IDOK) {
    // learn the dir by getting the first part of the filepath...
    m_sOpenFileDir= dlg.GetPathName();
    m_sOpenFileDir= m_sOpenFileDir.Left( dlg.m_ofn.nFileOffset); // leave only the d:\dir\dir

    // save that dir for next time...
    theApp.WriteProfileString("Prefs", "OpenFileDir", m_sOpenFileDir );

    // now take the desired action (read the file, etc...)
The result is:
* The very first time your program runs, m_sOpenFileDir will get set to C:\My Documents (a standard default).

* Whenever the user OKs the OpenFile dlg, you will assume that that is his preferred directory, so you save it to the registry.

* Thereafter, each time you use the Open File Dialog, it will remember the last place the user selected .. within the current run AND in future runs.

-- Dan

Author Comment

ID: 6312407
I had originally thought of saving the directory that the user has chosen but that would require me to put the above code in all the places that the CFileDialog is invoked. Presumably, inside the CFileDialog there is knowledge of what the last folder was since if FileOPen is used twice in a row, the second CFileDialog starts off in the folder where the first one finished.

Isn't there a way to extract from the CFileDialog where it would first open if it were invoked. In this case I just have get hold of this in the WM_CLOSE of the CMainFrame and save it once.
Will your db performance match your db growth?

In Percona’s white paper “Performance at Scale: Keeping Your Database on Its Toes,” we take a high-level approach to what you need to think about when planning for database scalability.

LVL 49

Expert Comment

ID: 6314281
Actually, it is a bit more complicated.  See the info on lpszInitialDir at this link (or in the MDSN documentation on the OPENFILENAME structure):


It seems that the system keeps a most-recently-used directory for each program -- probably in the registry somewhere. That will take effect in certain cases where you dont specify the initial dir and don't provide a filename.

>>Isn't there a way to extract from the CFileDialog where it would first open..

Nothing is documented, and simply instatiating a CFileDialog will certainly fail.  You would need to call DoModal(), which defeats the purpose.

>>that would require me to put the above code in all the places that the CFileDialog is invoked.

Most programs use this in only one or two places.  How hard is that?  

However, you can try this:  Never pass in a filename and leave lpszInitialDir pointing to "\0" -- that way the system will handle things in the default manor which you prefer.

-- Dan
LVL 30

Expert Comment

ID: 6314353
See following link for example project:


Author Comment

ID: 6314528
I should have explained what I was trying do better. I want to save the folder from which the user does a File/Open or File/Save As... When the user starts up next time they should be looking in the last folder, wherever it happens to be. In general our users will only use one folder! I would think that this would be a fairly standard thing to do. Our users don't want to always start in "My Documents" since that is where the unsophisticated user will always store stuff. This causes untold clutter.

When I look closer, it is the DocManager that executes OnFileOpen(...) which then passes an empty string on to DocManager::DoPromptFileName(...). If I can replace this DocManager::OnFileOpen() I could call the DoPromptFileName(...) with the last folder opened for the file name. Unfortunately, I can't get at the CFileDialog inside the DoPromptFileName to do my own saving of the file. Nor do I think that I can override any of DocManager's functions.

From Dan's comments, I think that I have to give up on getting at the last folder that is internal to the Windows function ::GetOpenFileName(&m_ofn). As he says, this is probably tucked away in some undocumented place.

One plan up for discussion would be to override the CWinApp::OnFileOpen() so that I can suggest a folder name. This is just a one liner:

void CWinApp::OnFileOpen()
     ASSERT(m_pDocManager != NULL);
Place within my override the following (comes from CDocManager::OnFileOpen():

    // prompt the user (with all document templates)
    CString newName;
    if (!DoPromptFileName(newName, AFX_IDS_OPENFILE,
        return; // open cancelled

    // if returns NULL, the user has already been alerted

and replace the CString newName; with the getting of the first file from the MRU list as in:

CSring newName = GetProfileString(_T("Recent File List"),

Does anyone have a better idea? Any time there is a File/Open or a File/Save the file is placed on the MRU list so my picking up this file would get me to the right place if everything works as expected.
LVL 49

Accepted Solution

DanRollins earned 800 total points
ID: 6314665
Hi Axter,
Did you read the question?

Hi emitchell,
From TN022 http://msdn.microsoft.com/library/en-us/vcmfc98/html/_mfcnotes_tn022.asp

ID_FILE_OPEN:   Opens an existing document.
Note   You must connect this to your CWinApp-derived class's message map to enable this functionality.

CWinApp::OnFileOpen has a very simple implementation of calling CWinApp::DoPromptFileName followed by CWinApp::OpenDocumentFile with the file or path name of the file to open. The CWinApp implementation routine DoPromptFileName brings up the standard FileOpen dialog and fills it with the file extensions obtained from the current document templates.

One common customization of ID_FILE_OPEN is to customize the FileOpen dialog or add additional file filters. The recommended way to customize this is to replace the default implementation with your own FileOpen dialog, and call CWinApp::OpenDocumentFile with the document's file or path name. There is no need to call the base class.

Therefore, you should simply porovide a handler for ID_FILE_OPEN, and in it, call CFileDialog and if the return is IDOK, call OpenDocumentFile()

-- Dan

Expert Comment

ID: 6315853

ur question seems similar lie the action we used to perform in winzip which stores the last extracted output folder..

y not create a key in the registry..the key  will hold the latest folder where a open or save information is performed..create a key in win registry...write into it the folder path..and b4 the user performs an open operation..or when the user clicks open icon or whatsoever read from the key and then let the folder where the operation ws perfomed be displayed

Author Comment

ID: 6317529
Dan's suggestion worked like a charm. I was trying to find a virtual function that I could add to when all I needed to do was to handle ID_FILE_OPEN in my main app. For the record I did the following. First pick up File1 from the MRU list in the InitInstance and save it into a member string variable:

    // find initial directory, if any and put it into
    // the string held within this class. it will only
    // be used once for the first open and then will
    // be erased
    m_sInitialDir = GetProfileString(RECENTFILELIST_KEY
     , _T("File1"));

Then handle the ID_FILE_OPEN with the following function:

    // use the initial dir the first time we prompt for a file
    // name. after a successful open, the file name will be
    // changed to be the empty string and the default dir
    // will be supplied by the CFileDialog internal memory
    if(!DoPromptFileName(m_sInitialDir, AFX_IDS_OPENFILE,
        // open cancelled
    // if returns NULL, the user has already been alerted

    // now erase the initial dir since we only want to use it once

The user must open something so we start off in the folder that corresponds to File1 of the MRU. After that, Windows keeps track of which folders we have navigated to so we can use an empty string within the same session.


Author Comment

ID: 6317540
Thanks Dan. You solved the problem. It was harder than I had originally thought!


Author Comment

ID: 6321610
Thanks Dan. You solved the problem. It was harder than I had originally thought!


Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction: Displaying information on the statusbar.   Continuing from the third article about sudoku.   Open the project in visual studio. Status bar – let’s display the timestamp there.  We need to get the timestamp from the document s…
Introduction: Dialogs (2) modeless dialog and a worker thread.  Handling data shared between threads.  Recursive functions. Continuing from the tenth article about sudoku.   Last article we worked with a modal dialog to help maintain informat…
This video will show you how to get GIT to work in Eclipse.   It will walk you through how to install the EGit plugin in eclipse and how to checkout an existing repository.
Sometimes it takes a new vantage point, apart from our everyday security practices, to truly see our Active Directory (AD) vulnerabilities. We get used to implementing the same techniques and checking the same areas for a breach. This pattern can re…

656 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question