我在開發中有一個命名空間擴展,我堅持從擴展內部以編程方式添加一個文件夾。在視覺上發生的是單擊工具欄按鈕,選擇文件路徑並且該文件是從中創建虛擬文件夾和文件的數據源。如何從命名空間擴展中將虛擬文件夾(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;
}
我應該採取什麼步驟讓文件夾以編程方式顯示?
SHCNE_UDPATEDIR說但是沒有人在看'newfoldername',因爲它不存在。該文檔說,「如果文件夾已被創建,刪除或重命名,分別使用SHCNE_MKDIR,SHCNE_RMDIR或SHCNE_RENAMEFOLDER。」 –
命名空間擴展數據源是與SHITEMIDLIST分離的樹結構。在更新數據源樹以從根上添加另一個分支並正確調用SHChangeNotify(謝謝)後,還需要採取其他哪些步驟才能讓Shell調用IShellFolder2 :: EnumObjects()? –
爲每個創建的目錄提升一個SHCNE_MKDIR。如果你創建了一個子目錄,那麼這意味着提升兩次,一次爲第一級目錄,一次爲第二級目錄 –