----------------------------------更新--------------- -------------------- 如果我执行以下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;
}
我使用shell命名空间扩展在Windows 7上创建了一个虚拟文件夹。然后我在另一个应用程序中弹出一个文件“另存为”对话框,并在对话框中的虚拟文件夹中选择一个特定的“文件夹”,文件对话框无法获取虚拟文件夹的路径。经过几次实验,我可以在文件“打开”对话框中获取文件夹的路径,如以下链接所述: 无法获取Windows 7 C ++上虚拟文件夹的路径(shell命名空间扩展相关) 但是当我使用类似的方式时实现文件“另存为”对话框,它不起作用。
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
,对话框会抛出异常。
我不是想在虚拟素材下创建一些东西,我只是想获得用户试图保存的路径。