How to hook an event to CFileDialog?

915 Views Asked by At

I'm trying to make a 'Save As' dialog with an event that would change the default path based on the type of file we choose from the filters combo box. The problem is, all the examples I've seen execute the code on result IDOK or IDCANCEL while I'd need the code to be executed while the dialog is still opened.

Also, is there any way to differentiate between what filter has been chosen if the filters have the same type? The GetFileExt() method just returns the extension but I have no way of telling if it was the first .my filter or the template .my filter.

I've seen something like LPOFNHOOKPROC but there was no example of how would I even use it and I'm not sure whether it would even solve my problem or not.

void CMyClass::OnFileOpen()
{
   CString pathNam;
   CString fileName;

   TCHAR szFilters[]= _T("MyType Files (*.my)|*.my|Template MyType (*.my)|*.my||");

   CFileDialog fileDlg(TRUE, _T("my"), _T("*.my"),
   OFN_FILEMUSTEXIST | OFN_HIDEREADONLY, szFilters);

   if(fileDlg.DoModal() == IDOK)
   {
       pathName = fileDlg.GetPathName();
       fileName = fileDlg.GetFileTitle();
   }
}

EDIT:

I am now able to get the specific filter that's been chosen by getting the OFN and checking the nFilterIndex value. So the remaining problem is whether I can update the path based on the chosen file format?

EDIT2:

I've found the OnChangeType method and overloaded it in the subclass and it indeed executes the method and the code within, but when I try to update the file path I get an access violation:

void TFileDialogExt::OnTypeChange()
{
   LPWSTR buff = L"C:\\TEST\\template.my";

   if(m_pOFN->nFilterIndex == 2)
      m_ofn.lpstrFile = buff;    
}
2

There are 2 best solutions below

4
Jovibor On

Basically you have to subclass CFileDialog and handle its CFileDialog::OnTypeChange method.

But, as suggested by Microsoft: you'd better use a new Common Item Dialog instead.

0
Andrew Truckle On

I did some research about this and found some useful questions:

Also, have a look at: SHCreateItemFromParsingName.


Here is a sample OnTypeChange handler:

void CMyFileDialog::OnTypeChange()
{
    {
        IFileOpenDialog* pfod = NULL;
        HRESULT hr = (static_cast<IFileDialog*>(m_pIFileDialog))->QueryInterface(IID_PPV_ARGS(&pfod));
        if (SUCCEEDED(hr))
        {
            IShellItem* psiInitialDir;

            CString strFolder = L"d:\\";
            hr = SHCreateItemFromParsingName(strFolder.GetString(), NULL, IID_PPV_ARGS(&psiInitialDir));
            if(SUCCEEDED(hr))
            {
                pfod->SetFolder(psiInitialDir);
            }
        }
    }

    CFileDialog::OnTypeChange();
}

My code uses a hard coded path for testing purposes, but you should now be able to complete your code:

  1. Determine which path you want to use based on the currently selected filter index.
  2. Use similar logic as here to navigate to that folder.