2016-11-21 213 views
1

我在開發中有一個命名空間擴展,我堅持從擴展內部以編程方式添加一個文件夾。在視覺上發生的是單擊工具欄按鈕,選擇文件路徑並且該文件是從中創建虛擬文件夾和文件的數據源。如何從命名空間擴展中將虛擬文件夾(IShellFolder)添加到資源管理器視圖?

因爲工具欄上的加載文件按鈕位於名稱空間擴展根目錄中,所以我想要發生的事情是讓新的虛擬文件夾自動出現。爲了顯示它,我需要單擊樹形視圖或從根目錄返回,然後出現文件夾。

我研究過這個問題,通常當這種情況發生時,人們正在使用SHChangeNotify。我試着像下面的例子那樣使用各種組合,比如提供名稱空間擴展根目錄下的路徑或pidl,下面的例子包括應該在那裏的新文件夾,使用該路徑的pidl(在SHChangeNotify中有適當的標誌)和仍然沒有骰子。我也嘗試了SHCNE_xxx,其中xxx是通知所有標誌。 SHChangeNotify(SHCNE_UPDATEDIR,SHCNF_IDLIST,retPidl,0);

右鍵單擊視圖窗格並選擇刷新不會調用要顯示的文件夾。

在獲取文件夾路徑的代碼中,我調用了我的文件夾的BindToObject,然後EnumObjects和Next,沒有命中斷點。當我點擊樹形視圖或上升一個文件夾並返回時,所有斷點都會被擊中。 SHChangeNotify不調用斷點。

的觀點在CreateViewObject使用SHCreateShellFolderView像這樣創建:

if (IID_IShellView == riid) { 
    SFV_CREATE csfv = {0}; 
    csfv.cbSize  = sizeof(SFV_CREATE); 
    hr    = QueryInterface(IID_PPV_ARGS(&csfv.pshf)); 
    if (SUCCEEDED(hr)) { 
     hr = CShellFolderView_CreateInstance(IID_PPV_ARGS(&csfv.psfvcb)); 
     if (SUCCEEDED(hr)) { 
      hr = SHCreateShellFolderView(&csfv, (IShellView**)ppv); 
      csfv.psfvcb->Release(); 
    m_hWnd = hwndOwner; 
     } 
     csfv.pshf->Release(); 
    } 
} 
在ShellVolderView類

,我設置的通知標誌的BP,他們從來沒有擊中。我讀過SF_UPDATEOBJECT需要返回的S_OK,所以我添加了這個。

IFACEMETHODIMP CShellFolderView::MessageSFVCB(UINT uMsg, WPARAM wParam, LPARAM lParam) { 
    HRESULT hr = E_NOTIMPL; 
    switch(uMsg) { 
     case SFVM_GETSORTDEFAULTS: 
      wParam = (WPARAM)(int*)-1; 
      lParam = (LPARAM)(int*)Col::Size; 
      hr  = S_OK; 
      break; 
     case SFVM_GETNOTIFY: 
      *((LONG*)lParam) = SHCNE_ALLEVENTS; 
      hr     = S_OK; 
      break; 
    } 
    return hr; 
} 

*編輯:添加嫌疑功能。當* ppidl爲NULL時,返回E_INVALIDARG。

STDMETHODIMP CShellFolder::ParseDisplayName(HWND hwnd, IBindCtx *pbc, LPWSTR pszDisplayName, ULONG *pchEaten, PIDLIST_RELATIVE *ppidl, ULONG *pdwAttributes) { 
    HRESULT hr = E_INVALIDARG; 

    if (pszDisplayName && *ppidl) { 
     WCHAR szNameComponent[MAX_SIZE] = {}; 
     PWSTR pszNext     = PathFindNextComponent(pszDisplayName); 
     if (pszNext && *pszNext) { 
      // unsure of max length, can't use StringCchLength for this 
      size_t len  = lstrlen(pszDisplayName); 
      size_t nextLen = 0; 
      StringCchLength(pszNext, MAX_SIZE, &nextLen); 
      hr = StringCchCopyN(szNameComponent, MAX_SIZE, pszDisplayName, len - nextLen); 
     } 
     else { 
      hr = StringCchCopy(szNameComponent, MAX_SIZE, pszDisplayName); 
     } 
     if (SUCCEEDED(hr)) { 
      PathRemoveBackslash(szNameComponent); 
      PIDLIST_RELATIVE pidlCurrent = NULL; 
      LPPIDLDATA child    = m_pPidlMgr->GetSubItemFromPidl((LPCITEMIDLIST)ppidl); 
      hr        = m_pPidlMgr->Create(&pidlCurrent, child); 
      if (SUCCEEDED(hr)) { 
       if (pszNext && *pszNext) { 
        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 { 
        *ppidl = pidlCurrent; 
       } 
      } 
     } 
    } 
    return hr; 
} 

我應該採取什麼步驟讓文件夾以編程方式顯示?

+0

SHCNE_UDPATEDIR說但是沒有人在看'newfoldername',因爲它不存在。該文檔說,「如果文件夾已被創建,刪除或重命名,分別使用SHCNE_MKDIR,SHCNE_RMDIR或SHCNE_RENAMEFOLDER。」 –

+0

命名空間擴展數據源是與SHITEMIDLIST分離的樹結構。在更新數據源樹以從根上添加另一個分支並正確調用SHChangeNotify(謝謝)後,還需要採取其他哪些步驟才能讓Shell調用IShellFolder2 :: EnumObjects()? –

+1

爲每個創建的目錄提升一個SHCNE_MKDIR。如果你創建了一個子目錄,那麼這意味着提升兩次,一次爲第一級目錄,一次爲第二級目錄 –

回答

1

嘗試以下操作: 「嘿,如果有人在看`thenewfoldername`,他們應該刷新」

SFVM_GETNOTIFY: 
    begin 
    PDWORD(ALParam)^ := SHCNE_ALLEVENTS; 
    Result := S_OK; 
    end; 
+0

在SFVM_GETNOTIFY中,我現在按照您的建議設置標誌,並在lParam中設置pidl,但發出SHChangeNotify後卻調用了IShellFolder:EnumObjects或BindToObject。但是SFVM_FSNOTIFY現在正在被擊中。在用戶界面中沒有任何更改,該文件夾不會使用該樹顯示或不顯示,或者返回到根文件夾。 –

+0

如果使用DefShellView,則可以嘗試刪除SFVM_UPDATEOBJECT,SFVM_QUERYFSNOTIFY,SFVM_ADDOBJECT和SFVM_FSNOTIFY處理程序。如果這個值只是返回E_NOTIMPL,因爲這個值應該由DefShellView處理。 –

+0

這是有道理的。我盲目地說,在這些情況下做任何事情都沒有問題。感謝那。我越來越近了,但EnumObject仍然沒有在通過SHChangeNotify發送事件通知後被調用。我想一旦調用了EnumObjects,Explorer將通過調用Enumerator接口顯示新數據,然後創建SHITEMID。有任何想法嗎? –

相關問題