0

----------------------------------更新--------------- -------------------- 如果我执行以下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,对话框会抛出异常。 在此处输入图像描述

我不是想在虚拟素材下创建一些东西,我只是想获得用户试图保存的路径。

4

0 回答 0