Я изучаю, как реализовать расширение пространства имен.
NSE должна отображать файлы и папки (они физические файлы и папки, но находятся в другом месте на диске).
Кроме того, NSE должна вести себя как можно ближе к обычному представлению Explorer, например в нем должны быть:
- Контекстные меню, которые обычно появляются в обычном представлении проводника, которые применимы к выбранным файлам / папкам.
- Перетаскивание (как файлов / папок, так и других вещей, таких как записки документов)
- 'Перетаскивание правой кнопкой мыши' (например, 7Zips 'Извлечь здесь ...')
- Копирование / вырезание / вставка из буфера обмена
- Поделиться с записями
- Все зарегистрированные обработчики наложения значков оболочки должны работать (например, Tortoise SVN / GIT)
- Подбор размеров колонки / повторный заказ
- Просмотр настроек, включая порядок и группировку
Итак, в основном все, что может сделать представление проводника, мы должны делать именно так.
Глядя на все, что может делать 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 будет загружен проводником, будет вызван конструктор, но сразу после этого будет вызван деструктор. Если я изменил интерфейсы обратно на прежние, он загорелся (но все еще с той же проблемой).
С тех пор я искал образец, реализующий IShellFolder2, но, опять же, документация так же плоха, как и для остальных этих API.
Как я могу использовать SHCreateShellFolderView, чтобы мне не пришлось заново реализовывать все, что уже делает Explorer?