2010-05-17 86 views
0

在我的C++ Windows應用程序中,我有一個應該允許最終用戶選擇文件夾的功能。我正在使用SHBrowseForFolder,它工作正常,除了文件夾快捷方式沒有顯示在對話框中。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; 
}; 

那麼,我在哪裏?好吧,我可以顯示文件夾,我可以顯示文件夾中的鏈接,但我不確定以下:

  1. 如何輕鬆地確定我是否有該項目是一個快捷方式鏈接到一個文件夾?我寫的代碼絕對不是看這個,並顯示任何捷徑鏈接。

  2. 我該如何輕鬆讓最終用戶將轉換成快捷方式鏈接所代表的文件夾?

  3. 這段代碼是否正確並且儘可能簡單/乾淨?

感謝您的幫助!

編輯:2010年6月1日:美國東部時間2:14: 在技術上提供的答案,所以我會標記出,我要問一個問題,幫我解決這個問題的代碼。

+0

用一些代碼更新您的問題,特別是您選擇的選項。 – 2010-05-17 20:58:43

+0

我用代碼更新了這個問題。感謝Hans。 – 2010-05-24 18:06:57

回答

0

更好的答案是使用IFileOpenDialog與FOS_PICKFOLDERS爲Windows Vista和以後的選項。

1

我想你可以添加BIF_BROWSEINCLUDEFILES樣式,然後過濾項設置爲僅顯示文件夾和.LNK的文件夾(這是你所追求的吧?)

要篩選項目,你需要添加一個回調FUNC鍵,BROWSEINFO,趕BFFM_IUNKNOWN和查詢IFolderFilterSite並設置filter

+0

嗨安德斯,這幫了我,但我的代碼是不是我需要它的水平:任何建議? – 2010-05-24 18:07:34