close
  • Hint

IFileOpenDialog and IFileSaveDialog, you can implement the IFileDialogEvents::OnFolderChanging event callback to prevent navigation to unwanted folders, by simply returning an error HRESULT value other than S_OK or E_NOTIMPL.

https://stackoverflow.com/questions/13443660/limit-directory-with-getopenfilename

 

  •  

 

Requests the form of an item's display name to retrieve through IShellItem::GetDisplayName and SHGetNameFromIDList.

EX:

IShellItem *psiResult;

PWSTR pszFilePath = NULL;

hr=psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ishellitem-getdisplayname

NOTE:透過GetDisplayName取得dlg所選取的路徑

 

IShellItem interface

image

https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ishellitem

 

image

https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nf-shobjidl_core-ifiledialogevents-onfolderchanging

透過OnFolderChanging Event取得當前路徑

 

class CDialogEventHandler : public IFileDialogEvents,

                            public IFileDialogControlEvents

{

IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };

};

        // Create an event handling object, and hook it up to the dialog.

        IFileDialogEvents *pfde = NULL;

        hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));

 

 

  • EventHandler Class
  • 透過CDialogEventHandler_CreateInstance與主程式中的 IFileDialogEvents 建立event

 

HRESULT CDialogEventHandler::OnFolderChange(IFileDialog* pfd)

{

 

    IFileSaveDialog* pfsd;

    HRESULT hr = pfd->QueryInterface(&pfsd);

    IShellItem* psiResult;

 

    hr = pfsd->GetCurrentSelection(&psiResult);

    if (SUCCEEDED(hr))

    {

         // We are just going to print out the name of the file for sample sake.

         size_t newsize = strlen(default_dir) + 1;

         wchar_t* wcstring = new wchar_t[newsize];

 

         // Convert char* string to a wchar_t* string.

         size_t convertedChars = 0;

         mbstowcs_s(&convertedChars, wcstring, newsize, default_dir, _TRUNCATE);

 

         MessageBox(NULL, wcstring, L"Save only in the path:", NULL);

 

         this->SetDefault(pfsd);

    }

 

    hr = pfsd->GetFolder(&psiResult);

    if (SUCCEEDED(hr))

    {

        

         //get displayname

         PWSTR pszFilePath = NULL;

         hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH, &pszFilePath);

         if (SUCCEEDED(hr))

         {

             CString s(pszFilePath);

             CString s1(default_dir);

             if (s.CompareNoCase(s1) != 0)

                  this->SetDefault(pfsd);

         }

    }

    psiResult->Release();

    pfsd->Release();

    return S_OK;

判斷folder change

image

 

HRESULT CDialogEventHandler::SetDefault(IFileSaveDialog* pfsd)

{

    //set default

    if (default_dir)

    {

         PIDLIST_ABSOLUTE pidl;

         WCHAR wstarting_dir[MAX_PATH];

         WCHAR* wc = wstarting_dir;

         for (const char* c = default_dir; *c && wc - wstarting_dir < MAX_PATH - 1; ++c, ++wc)

         {

             *wc = *c == '/' ? '\\' : *c;

         }

         *wc = 0;

 

         HRESULT hresult = ::SHParseDisplayName(wstarting_dir, 0, &pidl, SFGAO_FOLDER, 0);

         if (SUCCEEDED(hresult))

         {

             IShellItem* psi;

             hresult = ::SHCreateShellItem(NULL, NULL, pidl, &psi);

             if (SUCCEEDED(hresult))

             {

                  pfsd->SetFolder(psi);//rex

                  //SetDefault(pfsd);

             }

             ILFree(pidl);

         }

    }

 

    return S_OK;

}

 

Set path as default

image

 

完整範例可參考MS GitHub Example:

Windows-classic-samples-master\Samples\Win7Samples\winui\shell\appplatform\commonfiledialog

 

msdn:

https://docs.microsoft.com/en-us/previous-versions/windows/desktop/legacy/bb776913(v=vs.85)?redirectedfrom=MSDN

 

或我的demo code:

https://github.com/rex4ssd/VC2019_MFCIFileDialog

arrow
arrow
    文章標籤
    c++教學 IfileSaveDialog MFC
    全站熱搜

    天才R 發表在 痞客邦 留言(0) 人氣()