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); |
NOTE:透過GetDisplayName取得dlg所選取的路徑 |
IShellItem interface
https://docs.microsoft.com/en-us/windows/win32/api/shobjidl_core/nn-shobjidl_core-ishellitem |
|
|
透過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));
|
|
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
|
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
|
完整範例可參考MS GitHub Example:
Windows-classic-samples-master\Samples\Win7Samples\winui\shell\appplatform\commonfiledialog
或msdn:
或我的demo code:
https://github.com/rex4ssd/VC2019_MFCIFileDialog
留言列表