TStrings - ShellListView - ShellTreeView.

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
lexusrus
Сообщения: 2
Зарегистрирован: 26 апр 2006, 14:56

Здравствуйте, уважаемые программеры! Такой вопрос. Пользователь с помощью стандартных диалогов выбирает файлы и папки, которые со всем содержимым добавляются в TStrings. А задача заключается в том, чтобы в каком-нибудь визуальном компоненте отобразить структуру TStrings, т.е. в корневом каталоге будут все файлы и папки, которые были добавлены непосредственно, при щелчке на папке, показывается ее содержимое. У меня есть только вариант, когда все выбранные объекты копируются в отдельную папку на диске, а потом эта папка отображается в ShellTreeView. Но хочется все сделать виртуально.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Предлагаю использовать обычный TreeView. Иконки для элементов можно получать через SHGetFileInfo. Контекстное меню тоже можно выдрать из системы, но это уже немного потруднее. Могу кинуть готовый код как это делается, если понадобится.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
lexusrus
Сообщения: 2
Зарегистрирован: 26 апр 2006, 14:56

Да, если можно, то кинь.
Аватара пользователя
Romeo
Сообщения: 3126
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

Код: Выделить всё

#include <shlobj.h>
#include <atlbase.h>

...

void ShowContextMenu(HWND hWnd, LPCTSTR pszPath, int x, int y)
{
   USES_CONVERSION;

   // Строим полное имя файла/каталога
   TCHAR tchFullPath[MAX_PATH];
   GetFullPathName(pszPath, sizeof(tchFullPath)/sizeof(TCHAR), tchFullPath, NULL);

   // Получаем интерфейс IShellFolder рабочего стола
   IShellFolder *pDesktopFolder;
   SHGetDesktopFolder(&pDesktopFolder);

   // Преобразуем заданный путь в LPITEMIDLIST
   LPITEMIDLIST pidl;
   pDesktopFolder->ParseDisplayName(hWnd, NULL, T2OLE(tchFullPath), NULL, &pidl, NULL);

   // Ищем последний идентификатор в полученном списке pidl
   LPITEMIDLIST pLastId = pidl;
   USHORT temp;
   while(1)
   {
       int offset = pLastId->mkid.cb;
       temp = *(USHORT*)((BYTE*)pLastId + offset);

       if(temp == 0)
           break;

       pLastId = (LPITEMIDLIST)((BYTE*)pLastId + offset);
   }
   
   // Получаем интерфейс IShellFolder родительского объекта для заданного файла/каталога
   // Примечание: родительский каталог идентифицируется списком pidl за вычетом последнего
   //             элемента, поэтому мы временно зануляем pLastId->mkid.cb, отрезая его от списка
   temp = pLastId->mkid.cb;
   pLastId->mkid.cb = 0;
   IShellFolder *pFolder;
   pDesktopFolder->BindToObject(pidl, NULL, IID_IShellFolder, (void**)&pFolder);

   // Получаем интерфейс IContextMenu для заданного файла/каталога
   // Примечание: относительно родительского объекта заданный файл/каталог идентифицируется
   //             единственным элементом pLastId
   pLastId->mkid.cb = temp;
   IContextMenu *pContextMenu;
   pFolder->GetUIObjectOf(
      hWnd, 1, (LPCITEMIDLIST *)&pLastId, IID_IContextMenu, NULL, (void**)&pContextMenu);

   // Создаём меню
   HMENU hPopupMenu = CreatePopupMenu();

   // Заполняем меню
   pContextMenu->QueryContextMenu(hPopupMenu, 0, 1, 0x7FFF, 0);

   // Отображаем меню
   UINT nCmd = TrackPopupMenu(hPopupMenu,
      TPM_LEFTALIGN|TPM_LEFTBUTTON|TPM_RIGHTBUTTON|TPM_RETURNCMD, x, y, 0, hWnd, 0);

   // Выполняем команду (если она была выбрана)
   if(nCmd)
   {
      CMINVOKECOMMANDINFO ici;
      ZeroMemory(&ici, sizeof(CMINVOKECOMMANDINFO));
      ici.cbSize = sizeof(CMINVOKECOMMANDINFO);

      ici.hwnd = hWnd;
      ici.lpVerb = MAKEINTRESOURCE(nCmd-1);
      ici.nShow = SW_SHOWNORMAL;

      pContextMenu->InvokeCommand(&ici);
   }

   // Получаем интерфейс IMalloc
   IMalloc *pMalloc;
   SHGetMalloc(&pMalloc);

   // Освобождаем память, выделенную для pidl
   pMalloc->Free(pidl);

   // Освобождаем все полученные интерфейсы
   pDesktopFolder->Release();
   pFolder->Release();
   pContextMenu->Release();
   pMalloc->Release();

   return;
}
Код взят с RSDN'а:
http://www.rsdn.ru/article/qna/winshell/filemenu.xml

Там также есть очень краткие коментарии, хотя, думаю, и так всё понятно.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Ответить