У меня есть расширение пространства имен в разработке, и я застрял, добавляя папку программно изнутри расширения. Что происходит визуально, нажатие кнопки панели инструментов, выбор пути к файлу, и этот файл является источником данных, из которого создаются виртуальные папки и файлы.Как добавить виртуальную папку (IShellFolder) в представление Проводника из расширения пространства имен?
Что я хочу делать, так как кнопка загрузки файла на панели инструментов находится в корне расширений пространства имен, для автоматической отображения новой виртуальной папки. Чтобы он появился, мне нужно щелкнуть древовидное представление или выйти из корня и обратно. Тогда папка присутствует.
Я исследовал эту проблему, и обычно, когда это происходит, люди используют SHChangeNotify. Я попробовал это, как в примере ниже, и использовал различные комбинации, такие как предоставление пути или pidl из корня расширения пространства имен, пример ниже, включая новую папку, которая должна быть там, с помощью pidl этого пути (с соответствующим флагом в SHChangeNotify) и все еще нет кубиков. Я также попробовал SHCNE_xxx, где xxx - флаг всех уведомлений. SHChangeNotify (SHCNE_UPDATEDIR, SHCNF_IDLIST, retPidl, 0);
Щелчок правой кнопкой мыши по области просмотра и выбирая обновление не вызывает появление папки.
В коде, который получает путь к папке, я вызвал BindToObject моей папки, а затем EnumObjects и Next, точки останова не пострадали. Когда я нажимаю на древовидную структуру или поднимаю папку и отступаю, все точки останова попадают. SHChangeNotify не вызывает точки останова.
Вид создается с помощью SHCreateShellFolderView в CreateViewObject так:
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, я поставил п.н. на флаги уведомления, и они никогда не попадают. Я прочитал, что для SFVM_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 говорит: "Эй, если кто-то смотрит на' thenewfoldername', они должны обновить." Но никто не смотрит на 'thenewfoldername', потому что его не существует. В документации говорится: «Если папка была создана, удалена или переименована, используйте SHCNE_MKDIR, SHCNE_RMDIR или SHCNE_RENAMEFOLDER соответственно». –
Источник данных расширения пространства имен является древовидной структурой, отдельно от SHITEMIDLIST. После обновления дерева источника данных, чтобы добавить другую ветку от корня и правильно вызвать SHChangeNotify (спасибо), какие еще шаги я должен предпринять, чтобы получить/попросить Shell вызвать IShellFolder2 :: EnumObjects()? –
Поднимите один SHCNE_MKDIR для каждого созданного каталога. Если вы создали под-подкаталог, то это означает, что он поднимает его дважды, один раз для каталога первого уровня и один раз для каталога второго уровня –