代码之家  ›  专栏  ›  技术社区  ›  mjn anonym

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

  •  2
  • mjn anonym  · 技术社区  · 15 年前

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

    例如,如果文件夹包含pom.xml文件,则会出现maven项目符号。

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

    到目前为止,我所知道的所有解决方案都需要在整个系统范围内进行更改,但是是否还有一个解决方案可以在不修改系统的情况下仅适用于当前应用程序?

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

    例如,如果文件夹包含pom.xml文件,则会出现maven项目符号。

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

    到目前为止,我所知道的所有解决方案都需要在整个系统范围内进行更改,但是是否还有一个解决方案可以在不修改系统的情况下仅适用于当前应用程序?

    alt text

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

    2 回复  |  直到 15 年前
        1
  •  2
  •   Sertac Akyuz    15 年前

    从“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;
    


    缺点是,所有节点都必须使用ImageList中的图像,也就是说,系统图像列表中不会有图像。下面的示例演示如何为不需要自定义的节点检索系统映像。它在个人文件夹中为“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;
    

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

        2
  •  1
  •   RRUZ    15 年前

    这个 IShellIconOverlay 以及 IShellIconOverlayIdentifier 接口用于构建覆盖图标外壳扩展,这些扩展是系统范围的,而不是每个应用程序,在Delphi中,这两个接口都存在于shlobj单元中。

    请检查此链接以获取示例

    更新

    我想在你问题中发布的NetBeans IDE对话框中,使用自定义图标和标准控件绘制他们自己的对话框。您可以使用标准VCL控件创建自己的对话框,获得相同的效果。

    推荐文章