fidel espanto
fidel espanto

Reputation: 31

How to change the current directory of a Explorer-type custom dialog?

I'm currently customizing an Explorer-type custom dialog and I want to add a recent file combo box. I have already added the combo box the recent file items. I was also able to map them to their file path. But I'm having problems on changing the working directory of the explorer type dialog. Upon selecting a file on the combo box, I want the directory to change with the corresponding folder location of the selected file. See image attached.

Recent File Combo Box

  // Get the index of the selected item in the combo box
  const int iCmbIdx = CBGetCurSel(cOPEN_RECENTFILE_CMB);
  if (iCmbIdx < 0) break; // Break if it is invalid

  
  int iDefaultFileIndex = -1;
  // Key - value pair 
  // Returns the index of the file saved in registry
  int iFileIdx = lIndex.GetValue(iCmbIdx, iDefaultFileIndex);
  if (iFileIdx < 0 ) break; // Index not found


  // Build the folder path
  tchar szItem[LSTR];
  tchar szFilePath[LSTR];
  tsprintf(szItem, TEXT("File%d"), iFileIdx);
  LUserSettingGetString(TEXT("RecentFileList"), szItem, TEXT(""), szFilePath);
  if (szFilePath[0] == 0) break;
  LFile::GetFolderFromPath(szFilePath, szFilePath);

  if (!SetCurrentDirectory(szFilePath)) {
     LFDEBUG("SetCurrentDirectory failed (%d)\n", GetLastError());
     break;
  }

There are no errors in SetCurrentDirectory() call but the dialog will not go to the specified location. Is this the correct API to use to change the location of the folder?

This is the flags I used for the OPENFILENAME structure:

   ofn.Flags = OFN_ALLOWMULTISELECT | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST  | OFN_EXPLORER | OFN_HIDEREADONLY | OFN_ENABLETEMPLATE | OFN_ENABLEHOOK;

Upvotes: 1

Views: 388

Answers (1)

Anders
Anders

Reputation: 101774

SetCurrentDirectory is too low level, these dialogs use the shell namespace to navigate.

The classic open/save dialog API provides some messages to control it but changing the directory is not one of them. This leaves you with hacks like this:

void SetOpenSaveDlgFolderWithTextHack(HWND hTopDlg, LPCTSTR Path)
{
    HWND hCtl = GetDlgItem(hTopDlg, 0x47C); // Combo
    if (!hCtl) hCtl = GetDlgItem(hTopDlg, 0x480); // Old Edit
    if (hCtl && *Path && (int)(INT_PTR) SendMessage(hCtl, WM_SETTEXT, 0, (SIZE_T) Path) > 0)
    {
        SendMessage(hTopDlg, WM_COMMAND, IDOK, (SIZE_T) GetDlgItem(hTopDlg, IDOK));
    }
}

void SetOpenSaveDlgFolderWithShellBrowserHack(HWND hTopDlg, LPCTSTR Path)
{
    UINT cwm_getishellbrowser = WM_USER + 7;
    IShellBrowser *pSB, *pUnk = (IShellBrowser*) SendMessage(hTopDlg, cwm_getishellbrowser, 0, 0);
    if (pUnk && SUCCEEDED(pUnk->QueryInterface(IID_IShellBrowser, (void**) &pSB)))
    {
        if (PIDLIST_ABSOLUTE pidl = ILCreateFromPath(Path))
        {
            pSB->BrowseObject(pidl, SBSP_ABSOLUTE);
            ILFree(pidl);
        }
        pSB->Release();
    }
    else
    {
        SetOpenSaveDlgFolderWithTextHack(hTopDlg, Path);
    }
}

To find hTopDlg, use OFN_ENABLEHOOK and call GetParent on the HWND given to you in the hook proc for WM_NOTIFY:CDN_INITDONE.

As mentioned by Simon Mourier in the comments, the new dialogs added in Vista allows you to call IFileDialog::SetFolder to change the current folder. The downside of this API is that you don't have full control of the dialog layout and you have to implement a COM object to catch events.

Upvotes: 1

Related Questions