Я изучал, как реализовать расширение пространства имен.
В NSE должны отображаться файлы и папки (это физические файлы и папки , но , расположенные в другом месте на диске ).
Кроме того, NSE должен вести себя как можно ближе к обычному представлению Explorer , например. должно иметь:
- Контекстные меню, которые обычно отображаются в обычном представлении проводника, которые применимы к выбранным файлам / папкам
- Перетаскивание (как файлов / папок, так и других вещей, таких как обрывки документов)
- «Перетаскивание вправо» (например, 7Zips «Извлечь здесь ...»)
- Буфер обмена Копировать / Вырезать / Вставить
- Поделиться с записями
- Должны работать любые зарегистрированные обработчики оверлея Icon Shell (например, Tortoise SVN / GIT)
- Размер колонки / повторный заказ
- Просмотр настроек, включая порядок и группировку
Итак, все, что может сделать представление Explorer, мы должны.
Глядя на все то, что Explorer может делать (что я привык считать само собой разумеющимся) , я чувствовал себя немного ошеломленным.
Поскольку я ленивый и реалист (я понимаю, что практически невозможно воспроизвести всю эту функциональность без проблем), я планирую повторно использовать функциональность представления Explorer в моем NSE .
Я смотрел на различные образцы NSE. Большинство из них используют виртуальные данные, но, как я уже сказал, я представляю физические файлы и папки в другом месте на диске. Я также читал о методе SHCreateShellFolderView
.
Вооружившись этой информацией, я подумал, что это будет относительно простой случай предоставления PIDL
моей корневой папки, а затем в моем IShellFolder::CreateViewObject
вызове SHCreateShellFolder
метода. Вот этот метод:
STDMETHODIMP CShellFolderImpl::CreateViewObject(
HWND hwndOwner,
REFIID riid,
void** ppvOut )
{
HRESULT hr=E_NOINTERFACE;
if ( NULL == ppvOut )
return E_POINTER;
*ppvOut = NULL;
if (riid == IID_IShellView)
{
SFV_CREATE SfvCreate =
{
sizeof(SFV_CREATE)
};
if (SUCCEEDED(hr = QueryInterface(IID_PPV_ARGS(&SfvCreate.pshf))))
{
hr = ::SHCreateShellFolderView(
&SfvCreate,
reinterpret_cast<IShellView **>(ppvOut));
}
SfvCreate.pshf->Release();
}
else if (riid == IID_ITransferSource)
{
}
return hr;
}
Нет такой удачи с этим. SHCreateShellFolderView
всегда возвращался E_NOTIMPL
. Оказывается, это потому, что для этого требуется указатель на что-то, реализующее IShellFolder2
(и IPersist2
для GetCurFolder
, где я могу предоставить свой PIDL
). Моя папка только что реализована IShellFolder
и IPerist
.
Итак, изменив их для реализации новых интерфейсов, я получил ... ничего! NSE будет загружен Explorer, будет вызван конструктор, но сразу после этого будет вызван деструктор. Если я изменил интерфейсы обратно на те, что были, он загорелся (но все равно с той же проблемой).
С тех пор я искал образец, который реализует IShellFolder2
, но, опять же, документация такая же плохая, как и для остальных этих API.
Как я могу использовать SHCreateShellFolderView
, чтобы мне не пришлось переопределять все, что уже делает Explorer?