Как получить путь к виртуальной папке в диалоге сохранения файла?

———————————-Обновить————————————
Если я реализую ParseDislayName как показано ниже, диалоговое окно сообщит: «Файл уже существует, вы хотите заменить его?»:

HRESULT CFolderViewImplFolder::ParseDisplayName(HWND hwnd, IBindCtx *pbc, PWSTR pszName,
ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes)
{
HRESULT hr = E_INVALIDARG;

if (NULL != pszName)
{
WCHAR szNameComponent[MAX_PATH] = {};

// extract first component of the display name
PWSTR pszNext = PathFindNextComponent(pszName);
if (pszNext && *pszNext)
{
hr = StringCchCopyN(szNameComponent, ARRAYSIZE(szNameComponent), pszName, lstrlen(pszName) - lstrlen(pszNext));
}
else
{
hr = StringCchCopy(szNameComponent, ARRAYSIZE(szNameComponent), pszName);
}

if (SUCCEEDED(hr))
{
PathRemoveBackslash(szNameComponent);

UINT uIndex = 0;
hr = GetIndexFromDisplayString(szNameComponent, &uIndex);
if (SUCCEEDED(hr))
{
BOOL fIsFolder = ISFOLDERFROMINDEX(uIndex);
PIDLIST_RELATIVE pidlCurrent = NULL;
hr = CreateChildID(szNameComponent, fIsFolder, &pidlCurrent);
if (SUCCEEDED(hr))
{
// If there are more components to parse, delegate to the child folder to handle the rest.
if (pszNext && *pszNext)
{
// Bind to current item
IShellFolder *psf;
hr = BindToObject(pidlCurrent, pbc, IID_PPV_ARGS(&psf));
if (SUCCEEDED(hr))
{
PIDLIST_RELATIVE pidlNext = NULL;
hr = psf->ParseDisplayName(hwnd, pbc, pszNext, pchEaten, &pidlNext, pdwAttributes);
if (SUCCEEDED(hr))
{
*ppidl = ILCombine(pidlCurrent, pidlNext);
ILFree(pidlNext);
}
psf->Release();
}

ILFree(pidlCurrent);
}
else
{
// transfer ownership to caller
*ppidl = pidlCurrent;
}
}
}
}
}
return hr;
}

Я использую расширение пространства имен оболочки для создания виртуальной папки в Windows 7.
Затем я вызываю диалоговое окно «Сохранить как» в другом приложении и в диалоговом окне выбираю определенную «папку» в виртуальной папке, при этом диалоговое окно не может найти путь к виртуальной папке.
После нескольких экспериментов я могу получить путь к папке в диалоге открытия файла, как описано в этой ссылке:
невозможно получить путь к виртуальной папке в Windows 7 C ++ (связано расширение пространства имен оболочки)
Но когда я использую аналогичный способ для реализации диалога «Сохранить как», он не работает.

class CDialogEventHandler : public IFileDialogEvents,
public IFileDialogControlEvents
{
public:
// IUnknown methods
IFACEMETHODIMP QueryInterface(REFIID riid, void** ppv)
{
static const QITAB qit[] = {
QITABENT(CDialogEventHandler, IFileDialogEvents),
QITABENT(CDialogEventHandler, IFileDialogControlEvents),
{ 0 },
};
return QISearch(this, qit, riid, ppv);
}

IFACEMETHODIMP_(ULONG) AddRef()
{
return InterlockedIncrement(&_cRef);
}

IFACEMETHODIMP_(ULONG) Release()
{
long cRef = InterlockedDecrement(&_cRef);
if (!cRef)
delete this;
return cRef;
}

// IFileDialogEvents methods
IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnFolderChange(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnFolderChanging(IFileDialog *, IShellItem *) { return S_OK;
};
IFACEMETHODIMP OnHelp(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnSelectionChange(IFileDialog *) { return S_OK; };
IFACEMETHODIMP OnShareViolation(IFileDialog *, IShellItem *, FDE_SHAREVIOLATION_RESPONSE *) { return S_OK; };
IFACEMETHODIMP OnTypeChange(IFileDialog *pfd) { return S_OK; };
IFACEMETHODIMP OnOverwrite(IFileDialog *, IShellItem *, FDE_OVERWRITE_RESPONSE *) { return S_OK; };

// IFileDialogControlEvents methods
IFACEMETHODIMP OnItemSelected(IFileDialogCustomize *pfdc, DWORD dwIDCtl, DWORD dwIDItem) { return S_OK; };
IFACEMETHODIMP OnButtonClicked(IFileDialogCustomize *, DWORD) { return S_OK; };
IFACEMETHODIMP OnCheckButtonToggled(IFileDialogCustomize *, DWORD, BOOL) { return S_OK; };
IFACEMETHODIMP OnControlActivating(IFileDialogCustomize *, DWORD) { return S_OK; };

CDialogEventHandler() : _cRef(1) { };
private:
~CDialogEventHandler() { };
long _cRef;
};HRESULT CDialogEventHandler_CreateInstance(REFIID riid, void **ppv)
{
*ppv = NULL;
CDialogEventHandler *pDialogEventHandler = new (std::nothrow) CDialogEventHandler();
HRESULT hr = pDialogEventHandler ? S_OK : E_OUTOFMEMORY;
if (SUCCEEDED(hr))
{
hr = pDialogEventHandler->QueryInterface(riid, ppv);
pDialogEventHandler->Release();
}
return hr;
}

HRESULT VirtualFolderFileSave()
{
// CoCreate the File Open Dialog object.
//IFileSaveDialog *pfsd; also doesn't work
IFileDialog *pfd = NULL;
HRESULT hr = CoCreateInstance(CLSID_FileSaveDialog,
NULL,
CLSCTX_INPROC_SERVER,
IID_PPV_ARGS(&pfd));
if (SUCCEEDED(hr))
{

IFileDialogEvents *pfde = NULL;
hr = CDialogEventHandler_CreateInstance(IID_PPV_ARGS(&pfde));
if (SUCCEEDED(hr))
{
// Hook up the event handler.
DWORD dwCookie;
hr = pfd->Advise(pfde, &dwCookie);
if (SUCCEEDED(hr))
{

DWORD dwFlags = 0;
if (SUCCEEDED(hr))
{

hr = pfd->SetOptions(dwFlags | FOS_ALLNONSTORAGEITEMS | FOS_NOVALIDATE);

hr = pfd->SetFileTypes(ARRAYSIZE(c_rgSaveTypes), c_rgSaveTypes);

hr = pfd->SetDefaultExtension(L"apx");
if (SUCCEEDED(hr))
{
// Show the dialog
hr = pfd->Show(NULL);
if (SUCCEEDED(hr))
{
//never get here.......
IShellItem *psiResult;
hr = pfd->GetResult(&psiResult);
if (SUCCEEDED(hr))
{

PWSTR pszFilePath = NULL;
hr = psiResult->GetDisplayName(SIGDN_FILESYSPATH,
&pszFilePath);
if (SUCCEEDED(hr))
{

}
psiResult->Release();
}
}

}
}
// Unhook the event handler.
pfd->Unadvise(dwCookie);
}
pfde->Release();
}
pfd->Release();
}
return hr;
}

Я добавляю точку останова в IFACEMETHODIMP OnFileOk(IFileDialog *) { return S_OK; }; в приведенном выше коде, но он никогда не срабатывает после нажатия кнопки «Сохранить» в диалоговом окне файла. И как вы можете видеть в комментариях в приведенном выше коде, после появления диалогового окна оно никогда не возвращается после hr = pfd->Show(NULL);, Каждый раз, когда я нажимаю кнопку «Сохранить», он всегда сообщает об ошибке или генерирует исключения.

Я попытался реализовать следующее в виртуальной папке DLL,

//  Translates a display name into an item identifier list.
HRESULT CFolderViewImplFolder::ParseDisplayName(HWND /*hwnd*/, IBindCtx *  /*pbc*/, PWSTR /*pszName*/,
ULONG *  /*pchEaten*/, PIDLIST_RELATIVE *   /*ppidl*/, ULONG *  /*pdwAttributes*/)
{
return E_NOTIMPL;
}

Но когда он вернется E_NOTIMPLдиалоговое окно сообщает об ошибке «не реализовано», если возвращается S_OKДиалог выдает исключения.
введите описание изображения здесь

Я не пытаюсь создать что-то под виртуальным фодером, я просто хочу получить путь, по которому пользователь пытается сохранить.

0

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]