Как использовать пользовательские значки в диалоговом окне «Просмотр папки»? - PullRequest
2 голосов
/ 19 августа 2010

В диалоговом окне «Открыть проект ...» (см. Изображение ниже) в среде IDE NetBeans есть полезная функция, которая использует собственный значок для символов папки в зависимости от типа проекта в этой папке.

Например, если папка содержит файл pom.xml, появляется символ проекта Maven.

Возможно, в стандартном диалоговом окне Windows также есть точка расширения или элемент управления оболочки, который можно использовать для переопределения значка папки по умолчанию.

Для всех известных мне решений требуется общесистемное решение.изменить, но есть ли также решение, которое работает без системных модификаций и только для текущего приложения?

alt text

Обновление: какой компонент VCL вы бы предложили в качестве отправной точки для пользовательскогодиалоговое окно, можно ли использовать TShellTreeView или TcxShellTreeView?

Ответы [ 2 ]

2 голосов
/ 21 августа 2010

Исходя из 'TCustomTreeView', TShellTreeView поддерживает изображения из коробки. ImageList может быть присвоено его свойству Images, а в его событии OnGetImageIndex может быть указан индекс изображения в списке для соответствующего узла.

procedure TForm1.ShellTreeView1GetImageIndex(Sender: TObject; Node: TTreeNode);
begin
  if TShellFolder(Node.Data).DisplayName = 'RAD Studio' then
    Node.ImageIndex := 2;
end;


Недостатком является то, что все узлы должны будут использовать изображения в списке изображений, то есть не будет изображений из списка системных изображений. Приведенный ниже пример демонстрирует, как системные образы могут быть получены для узлов, которые не будут настроены. Он использует пользовательский образ для папки 'RAD Studio' в личной папке и использует системные образы для всех других узлов. ImageList1 содержит наши пользовательские изображения, ImageList2 - это то, что назначено свойству 'Images' в ShellTreeView.

type
  TForm1 = class(TForm)
    [...]
  private
    FShellImageList: THandle;
    [...]

uses
  shellapi, shellctrls, commctrl;

procedure TForm1.FormCreate(Sender: TObject);
var
  FileInfo: TSHFileInfo;
  ImageWidth, ImageHeight: Integer;
begin
  ShellTreeView1.Root := 'rfPersonal';

  FShellImageList := SHGetFileInfo('C:\', 0, FileInfo, SizeOf(FileInfo),
      SHGFI_SYSICONINDEX or SHGFI_SMALLICON);     //'//(pop SO formatting)
  ImageList_GetIconSize(FShellImageList, ImageWidth, ImageHeight);
  ImageList2.Width := ImageWidth;
  ImageList2.Height := ImageHeight;

  // Arbitrary count hopefully sufficient enough to be able to hold
  // system images. Note that this is a proof of concept, not to be
  // intended to be a working design.
  ImageList_SetImageCount(ImageList2.Handle, 255);

  // Make sure the width/height of ImageList1 is the same.
  // Set its size, populate, stretchdraw do whatever necessary..
end;

function GetShellImage(PIDL: PItemIDList; Open: Boolean): Integer;
var
  FileInfo: TSHFileInfo;
  Flags: Integer;
begin
  Flags := SHGFI_PIDL or SHGFI_SYSICONINDEX or SHGFI_SMALLICON;
  if Open then Flags := Flags or SHGFI_OPENICON;
  SHGetFileInfo(PChar(PIDL), 0, FileInfo, SizeOf(FileInfo), Flags);
  Result := FileInfo.iIcon;
end;

procedure TForm1.ShellTreeView1GetImageIndex(Sender: TObject; Node: TTreeNode);
var
  ImageIndex, SelectedIndex: Integer;
  Icon: TIcon;
begin
  if TShellFolder(Node.Data).DisplayName = 'RAD Studio' then begin
    Icon := TIcon.Create;
    try
      ImageList1.GetIcon(0, Icon);
      ImageIndex := ImageList_AddIcon(ImageList2.Handle, Icon.Handle);

      ImageList1.GetIcon(1, Icon);
      SelectedIndex := ImageList_AddIcon(ImageList2.Handle, Icon.Handle);
    finally
      Icon.Free;
    end;
  end else begin
    ImageIndex := GetShellImage(TShellFolder(Node.Data).AbsoluteID, False);
    SelectedIndex := GetShellImage(TShellFolder(Node.Data).AbsoluteID, True);

    ImageList_ReplaceIcon(ImageList2.Handle, ImageIndex,
        ImageList_GetIcon(FShellImageList, ImageIndex, 0));
    ImageList_ReplaceIcon(ImageList2.Handle, SelectedIndex,
        ImageList_GetIcon(FShellImageList, SelectedIndex, 0));
  end;
  Node.ImageIndex := ImageIndex;
  Node.SelectedIndex := SelectedIndex;
end;

Как прокомментировано в коде, это не следует принимать за работающий дизайн; Вместо списка изображений, имеющего много неиспользуемых изображений, можно использовать какой-то вид поиска, который соответствует «индексу изображения» и «системному индексу списка изображений».

1 голос
/ 19 августа 2010

Интерфейсы IShellIconOverlay и IShellIconOverlayIdentifier используются для создания расширений оболочки значков наложения, эти расширения являются общесистемными, а не приложениями, в delphi оба интерфейса существуют в модуле ShlObj.1005 *

проверьте эту ссылку для примера

ОБНОВЛЕНИЕ

Я думаю, что диалоговое окно IDE Netbeans, опубликованное в вашем вопросе, нарисует свое собственное диалоговое окно, используя пользовательские значки и стандартные элементы управления.Вы можете получить тот же эффект, создав собственное диалоговое окно, используя стандартные элементы управления vcl.

...