在我的C ++ Windows应用程序中,我有一个应该允许最终用户选择文件夹的功能。我正在使用SHBrowseForFolder并且它正常工作,除了文件夹快捷方式没有显示在对话框中。
有谁知道是否可以配置SHBrowseForFolder以便最终用户能够导航文件夹快捷方式?
编辑:2010年5月24日,美国东部时间1:10:
好的,我将展示到目前为止的代码。我已经尝试过在我的回调程序中使用BFFM_IUNKNOWN回调的建议,但一直在努力弄清楚如何提供一个有效的IFolderFilter后代。
1。被调用的代码:
Error CFolderChooserDialog::RunDialog()
{
Error runResult = kError_NotInitialized;
if (VERIFYN(kLyndsey, m_ReferenceCount > 0)) {
runResult = kError_Unexpected;
m_AllFoldersFilter = new TAllFoldersFilter();
if (VERIFYN(kLyndsey, m_AllFoldersFilter))
{
char selectedDirectoryBuffer[MAX_PATH];
m_DirectoryPath.CopyInto(selectedDirectoryBuffer);
BROWSEINFO bi;
memset(&bi, 0, sizeof(bi));
bi.hwndOwner = MyGetMainHWND(m_CBP);
bi.pidlRoot = NULL;
bi.pszDisplayName = selectedDirectoryBuffer;
bi.lpszTitle = (const char*)m_Description;
bi.ulFlags |= BIF_RETURNONLYFSDIRS;
bi.ulFlags |= BIF_BROWSEINCLUDEFILES;
bi.lpfn = SHBrowseForFolderCallbackProc;
bi.lParam = (LPARAM)this;
bi.iImage = 0;
LPITEMIDLIST resultInfo = SHBrowseForFolder(&bi);
if (resultInfo) {
runResult = kError_NoError;
if (SHGetPathFromIDList(resultInfo, selectedDirectoryBuffer)) {
m_DirectoryPath = selectedDirectoryBuffer;
}
}
else {
runResult = kError_Failed;
}
delete m_AllFoldersFilter;
m_AllFoldersFilter = nil;
CoTaskMemFree(resultInfo);
}
}
return runResult;
}
2。从SHBrowseForFolder调用的回调:
int CALLBACK CFolderChooserDialog::SHBrowseForFolderCallbackProc(HWND window, UINT message, LPARAM messageValue, LPARAM clientData)
{
CFolderChooserDialog* thisPtr = (CFolderChooserDialog*)clientData;
if (VERIFYN(kLyndsey, thisPtr)) {
switch (message) {
case BFFM_INITIALIZED: {
if (!thisPtr->m_DialogTitle.IsEmpty()) {
::SetWindowText(window, (const char*) thisPtr->m_DialogTitle);
}
if (!thisPtr->m_DirectoryPath.IsEmpty()) {
LPCTSTR startDirectory = thisPtr->m_DirectoryPath;
::SendMessage(window, BFFM_SETSELECTION, TRUE, (LPARAM)startDirectory);
}
break;
}
case BFFM_IUNKNOWN:
{
IUnknown* theInterface = (IUnknown*)messageValue;
if (VERIFYN(kLyndsey, theInterface))
{
IFolderFilterSite* filter = NULL;
theInterface->QueryInterface(IID_IFolderFilterSite, (void**)&filter);
if (VERIFYN(kLyndsey, filter))
{
filter->SetFilter((IUnknown*)thisPtr->m_AllFoldersFilter);
filter->Release();
}
}
break;
}
default:
break;
}
}
return 0;
}
3。应该为每个项目调用IFolderFilter,以便在对话框中或从对话框中过滤它:
class TAllFoldersFilter : public IFolderFilter
{
public:
TAllFoldersFilter() { refCount = 0;}
HRESULT STDMETHODCALLTYPE QueryInterface(const IID& iid, void** obj)
{
if (!obj)
return E_INVALIDARG;
*obj = NULL;
if (iid == IID_IUnknown || iid == IID_IFolderFilter)
{
*obj = (void*)this;
AddRef();
return NOERROR;
}
return E_NOINTERFACE;
}
ULONG STDMETHODCALLTYPE AddRef()
{
refCount++;
return refCount;
}
ULONG STDMETHODCALLTYPE Release()
{
refCount--;
return refCount;
}
HRESULT STDMETHODCALLTYPE GetEnumFlags(IShellFolder* sf, LPCITEMIDLIST pidlFolder, HWND* window, DWORD* flags)
{
return 0;
}
HRESULT STDMETHODCALLTYPE ShouldShow(IShellFolder* sf, LPCITEMIDLIST pidlFolder, LPCITEMIDLIST pidlItem)
{
HRESULT resultCode = S_OK;
ULONG attributes = 0UL;
if (SUCCEEDED(sf->GetAttributesOf(1, &pidlItem, &attributes)))
{
if (attributes & SFGAO_FOLDER)
{
resultCode = S_OK; // Yes, I see the folders
}
else if (attributes & SFGAO_LINK)
{
resultCode = S_OK; // Yes, this shows the folder shortcut links, but I cannot explore them. When I "expand" them (click on the plus-sign-box), nothing happens.
}
}
return resultCode;
}
protected:
ULONG refCount;
};
那么,我在哪里?好吧,我可以显示文件夹,我可以显示文件夹链接,但我不确定以下内容:
如何轻松确定我的项目是否是文件夹的快捷链接?我写的代码绝对不是在看,而是显示任何快捷方式链接。
如何轻松允许最终用户将转换为快捷方式链接所代表的文件夹?
这段代码是否正确且简单/干净?
感谢您的所有帮助!
编辑:2010年6月1日:美国东部时间2:14: 答案是技术上提供的,所以我会标记,我会问另一个问题,以帮助我修复此代码。
答案 0 :(得分:1)
我猜您可以添加BIF_BROWSEINCLUDEFILES样式,然后将项目过滤为仅显示文件夹,将.lnk过滤到文件夹(这就是您追求的对象?)
要过滤这些项目,您需要向BROWSEINFO添加回调功能,抓住BFFM_IUNKNOWN并查询IFolderFilterSite并设置filter
答案 1 :(得分:0)
更好的答案是将IFileOpenDialog与FOS_PICKFOLDERS一起用作Windows Vista及更高版本的选项。