代码之家  ›  专栏  ›  技术社区  ›  Lyndsey Ferguson

浏览文件夹和快捷方式

  •  0
  • Lyndsey Ferguson  · 技术社区  · 14 年前

    有人知道是否可以配置SHBrowseForFolder,以便最终用户能够浏览文件夹快捷方式吗?

    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;  
    }  
    

    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;  
    };  
    

    那么,我在哪里?嗯,我可以显示文件夹,我可以显示文件夹链接,但我不确定以下内容:

    1. 如何轻松确定我拥有的项目是否是指向文件夹的快捷链接?我写的代码绝对不是看这个,而是显示任何快捷链接。

    2. 如何让最终用户轻松地进行深入研究

    3. 此代码是否正确且尽可能简单/干净?

    谢谢你的帮助!

    答案是技术上提供的,所以我会标记它,我会问另一个问题来帮助我修复这个代码。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Anders    14 年前

    我想你可以添加BIF\u BROWSEINCLUDEFILES样式,然后过滤项目,只显示文件夹和.lnk的文件夹(这是你想要的,对吗?)

    要过滤这些项,您需要将回调函数添加到 BROWSEINFO ,接住 BFFM_IUNKNOWN 和查询 IFolderFilterSite filter

        2
  •  0
  •   Lyndsey Ferguson    14 年前

    更好的解决方法是在WindowsVista和更高版本中使用IFileOpenDialog和FOS\u PICKFOLDERS作为选项。