如何在“浏览文件夹”中使用自定义图标对话?

发布于 2024-09-15 05:04:19 字数 400 浏览 1 评论 0原文

NetBeans IDE 中的“打开项目...”对话框(见下图)中有一个很好的功能,它根据该文件夹中的项目类型使用文件夹符号的自定义图标。

例如,如果文件夹包含 pom.xml 文件,则会显示 Maven 项目符号。

也许 Windows 标准对话框或 shell 视图控件中还有一个扩展点,可用于覆盖默认文件夹图标。

到目前为止,我所知道的所有解决方案都需要进行系统范围的更改,但是是否还有一种无需系统修改且仅适用于当前应用程序的解决方案?

alt text

更新:您建议使用哪个 VCL 组件作为自定义对话框的起点,我可以使用 TShellTreeView 或 TcxShellTreeView 吗?

There is a nice feature in the "Open Project..." dialog (see image below) in the NetBeans IDE which uses a custom icon for the folder symbols depending on the project type in that folder.

For example, if a folder contains a pom.xml file, the Maven project symbol appears.

Maybe there also an extension point in the Windows standard dialog or a shell view control which can be used to override the default folder icon.

All solutions I know so far need a system-wide change, but is there also a solution which works without system modifications and only for the current application?

alt text

Update: which VCL component would you suggest as a starting point for a custom dialog, could I use TShellTreeView or TcxShellTreeView?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

紧拥背影 2024-09-22 05:04:20

继承自“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 是分配给“ShellTreeView”的“Images”属性的图像。

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;

正如代码中所注释的,这不应该被视为工作设计;可以采用某种匹配“图像索引”和“系统图像列表索引”的查找,而不是具有大量未使用图像的图像列表。

Descending from 'TCustomTreeView', TShellTreeView has support for images out of the box. An ImageList can be assigned to its Images property, and in its OnGetImageIndex event the index of the image in the list for the corresponding node can be supplied.

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

A downside of that is, all nodes will have to use the images in the imagelist, that is there won't be images from the system image list. The below example demonstrates how system images can be retrieved for nodes which won't be customized. It uses a custom image for 'RAD Studio' folder in the personal folder and uses system images for all other nodes. ImageList1 holds our custom images, ImageList2 is the one that is assigned to the 'Images' property of the '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;

As commented in the code, this should not be taken for a working design; Instead of an imagelist having lots of unused images, some kind of a lookup that matches 'image index' and 'system image list index' could be employed.

何处潇湘 2024-09-22 05:04:20

IShellIconOverlayIShellIconOverlayIdentifier 接口用于构建覆盖图标 shell 扩展,这些扩展是系统范围的,而不是针对每个应用程序的,在 delphi 中,这两个接口都存在于 ShlObj 单元中。

检查此链接的示例

更新

我认为 Netbeans IDE 对话框在您的问题中发布,使用自定义图标和标准控件绘制自己的对话框。您可以使用标准 vcl 控件构建自己的对话框以获得相同的效果。

The IShellIconOverlay and the IShellIconOverlayIdentifier Interfaces are used to build overlay icons shell extensions , theses extensions are system wide not per application, in delphi both interfaces exists in the ShlObj unit.

check this link for an example

UPDATE

i think wich the Netbeans IDE dialog posted in your question, draw their own dialog box using custom icons and standard controls. you can gain the same effect building your own dialog box using the standard vcl controls.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文