delphi - 如何在 "Browse for folder"对话框中使用自定义图标?

标签 delphi winapi dialog icons directory

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

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

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

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

alt text

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

最佳答案

源自“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;

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

关于delphi - 如何在 "Browse for folder"对话框中使用自定义图标?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3519185/

相关文章:

delphi - 寻找delphi的通信框架

c++ - 如何通过 MessageBox 输出一个指针?

android - 我在 Lollipop 上的 ProgressDialog 中看不到进度微调器

delphi - 如何在MainForm之前创建一个表单?

delphi - 防止保存时删除主体为空的方法

c# - C# 中的多媒体键盘的多媒体控制

iOS 8 - UIAlertController 按钮样式未正确应用

java - 在 JavaFX 对话框中获取两个以上的输入

java - 使用Union在Delphi应用程序和android应用程序之间进行通信

c++ - 窗口最大化