代码之家  ›  专栏  ›  技术社区  ›  Pauk

如何使用Delphi从文件扩展名中获取图标和描述?

  •  13
  • Pauk  · 技术社区  · 17 年前

    基本上,我有一个TcxGrid,它将列出各种文件名,我想根据文件扩展名提供更多详细信息,特别是它的描述(例如,对于.PDF,它是“Adobe Acrobat文档”)及其相关图标。

    我注意到有一个 very similar question already

    关于在哪里查找此类信息的建议很好,如果有类似于上面C#post(显然是Delphi)中提到的类,那就太好了。

    7 回复  |  直到 9 年前
        1
  •  19
  •   Pauk    17 年前

    感谢Rob Kennedy为我指明了ShGetFileInfo的方向。然后我在谷歌上找到了这两个例子- Delphi 3000 , Torry's

    而且,就在我完成比尔·米勒的回答时,他给了我最后一点我需要的帮助。最初,我将完整的文件名传递给ShGetFileInfo,这并不是我想要的。传递“*.EXT”建议的调整非常好。

    这个班可以做更多的工作,但它做了我需要的。它似乎可以处理没有相关细节的文件扩展名。

    unit FileAssociationDetails;
    
    {
      Created       : 2009-05-07
      Description   : Class to get file type description and icons.
                      * Extensions and Descriptions are held in a TStringLists.
                      * Icons are stored in a TImageList.
    
                      Assumption is all lists are in same order.
    }
    
    interface
    
    uses Classes, Controls;
    
    type
      TFileAssociationDetails = class(TObject)
      private
        FImages : TImageList;
        FExtensions : TStringList;
        FDescriptions : TStringList;
      public
        constructor Create;
        destructor Destroy; override;
    
        procedure AddFile(FileName : string);
        procedure AddExtension(Extension : string);    
        procedure Clear;    
        procedure GetFileIconsAndDescriptions;
    
        property Images : TImageList read FImages;
        property Extensions : TStringList read FExtensions;
        property Descriptions : TStringList read FDescriptions;
      end;
    
    implementation
    
    uses SysUtils, ShellAPI, Graphics, Windows;
    
    { TFileAssociationDetails }
    
    constructor TFileAssociationDetails.Create;
    begin
      try
        inherited;
    
        FExtensions := TStringList.Create;
        FExtensions.Sorted := true;
        FDescriptions := TStringList.Create;
        FImages := TImageList.Create(nil);
      except
      end;
    end;
    
    destructor TFileAssociationDetails.Destroy;
    begin
      try
        FExtensions.Free;
        FDescriptions.Free;
        FImages.Free;
      finally
        inherited;
      end;
    end;
    
    procedure TFileAssociationDetails.AddFile(FileName: string);
    begin
      AddExtension(ExtractFileExt(FileName));
    end;
    
    procedure TFileAssociationDetails.AddExtension(Extension : string);
    begin
      Extension := UpperCase(Extension);
      if (Trim(Extension) <> '') and
         (FExtensions.IndexOf(Extension) = -1) then
        FExtensions.Add(Extension);
    end;
    
    procedure TFileAssociationDetails.Clear;
    begin
      FExtensions.Clear;
    end;
    
    procedure TFileAssociationDetails.GetFileIconsAndDescriptions;
    var
      Icon: TIcon;
      iCount : integer;
      Extension : string;
      FileInfo : SHFILEINFO; 
    begin
      FImages.Clear;
      FDescriptions.Clear;
    
      Icon := TIcon.Create;
      try
        // Loop through all stored extensions and retrieve relevant info
        for iCount := 0 to FExtensions.Count - 1 do
        begin
          Extension := '*' + FExtensions.Strings[iCount];
    
          // Get description type
          SHGetFileInfo(PChar(Extension),
                        FILE_ATTRIBUTE_NORMAL,
                        FileInfo,
                        SizeOf(FileInfo),
                        SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES
                        );
          FDescriptions.Add(FileInfo.szTypeName);
    
          // Get icon and copy into ImageList
          SHGetFileInfo(PChar(Extension),
                        FILE_ATTRIBUTE_NORMAL,
                        FileInfo,
                        SizeOf(FileInfo),
                        SHGFI_ICON or SHGFI_SMALLICON or
                        SHGFI_SYSICONINDEX or SHGFI_USEFILEATTRIBUTES
                        );
          Icon.Handle := FileInfo.hIcon;
          FImages.AddIcon(Icon);
        end;
      finally
        Icon.Free;
      end;
    end;
    
    end.
    

    unit Main;
    
    {
      Created       : 2009-05-07
      Description   : Test app for TFileAssociationDetails.
    }
    
    interface
    
    uses
      Windows, Forms, FileAssociationDetails, Classes, Controls, ComCtrls;
    
    type
      TfmTest = class(TForm)
        PageControl1: TPageControl;
        procedure FormShow(Sender: TObject);
        procedure FormClose(Sender: TObject; var Action: TCloseAction);
      private
        { Private declarations }
        FFileDetails : TFileAssociationDetails;
      public
        { Public declarations }
      end;
    
    var
      fmTest: TfmTest;
    
    implementation
    
    {$R *.dfm}
    
    procedure TfmTest.FormShow(Sender: TObject);
    var
      iCount : integer;
      NewTab : TTabSheet;
    begin
      FFileDetails := TFileAssociationDetails.Create;
      FFileDetails.AddFile('C:\Documents and Settings\...\Test.XLS');
      FFileDetails.AddExtension('.zip');
      FFileDetails.AddExtension('.pdf');
      FFileDetails.AddExtension('.pas');
      FFileDetails.AddExtension('.XML');
      FFileDetails.AddExtension('.poo');
    
      FFileDetails.GetFileIconsAndDescriptions;
      PageControl1.Images := FFileDetails.Images;
    
      for iCount := 0 to FFileDetails.Descriptions.Count - 1 do
      begin
        NewTab := TTabSheet.Create(PageControl1);
        NewTab.PageControl := PageControl1;
        NewTab.Caption := FFileDetails.Descriptions.Strings[iCount];
        NewTab.ImageIndex := iCount;
      end;
    end;
    
    procedure TfmTest.FormClose(Sender: TObject; var Action: TCloseAction);
    begin
      PageControl1.Images := nil;
      FFileDetails.Free;
    end;
    
    end.
    

    谢谢大家的回答!

        2
  •  3
  •   Rob Kennedy    17 年前

    呼叫 ShGetFileInfo . 它可以告诉您描述(该函数词汇表中的“类型名称”),还可以给您一个图标句柄,或系统映像列表的句柄,图标所在的位置,或包含映像资源的模块的路径。这个函数可以做很多不同的事情,所以一定要仔细阅读文档。

    MSDN says “可能很慢”并呼叫 IExtractIcon 接口是“更灵活、更高效”的替代方案。但它建议的顺序是使用 IShellFolder 接口,然后调用 GetUIObjectOf 获取文件的 萃取管 GetIconLocation Extract 在其上检索图标的句柄。

    据我所知,这正是我想要的 ShGetFileInfo ShGetFileInfo 直到速度和效率成为一个明显的问题。

        3
  •  3
  •   Rob Kennedy    17 年前
    function GetGenericFileType( AExtension: string ): string;
    { Get file type for an extension }
    var
      AInfo: TSHFileInfo;
    begin
      SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
        SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES );
      Result := AInfo.szTypeName;
    end;
    
    function GetGenericIconIndex( AExtension: string ): integer;
    { Get icon index for an extension type }
    var
      AInfo: TSHFileInfo;
    begin
      if SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
        SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
      Result := AInfo.iIcon
      else
        Result := -1;
    end;
    
    function GetGenericFileIcon( AExtension: string ): TIcon;
    { Get icon for an extension }
    var
      AInfo: TSHFileInfo;
      AIcon: TIcon;
    begin
      if SHGetFileInfo( PChar( AExtension ), FILE_ATTRIBUTE_NORMAL, AInfo, SizeOf( AInfo ),
        SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
      begin
        AIcon := TIcon.Create;
        try
          AIcon.Handle := AInfo.hIcon;
          Result := AIcon;
        except
          AIcon.Free;
          raise;
        end;
      end
      else
        Result := nil;
    end;
    
        4
  •  2
  •   Bill Miller    17 年前
    uses ShellAPI;
    
    var
    AExtension: string;
    AFileType: string;    
    AListItem: TListItem;
    AFileInfo: TSHFileInfo;
    begin
    // get the extensions file icon
    AExtension := ExtractFileExt( FileName );
    if SHGetFileInfo( PChar( '*' + AExtension ), FILE_ATTRIBUTE_NORMAL, AFileInfo, SizeOf
      ( AFileInfo ), SHGFI_SYSICONINDEX or SHGFI_SMALLICON or SHGFI_USEFILEATTRIBUTES ) <> 0 then
      AIndex := AFileInfo.iIcon
    else
      AIndex := -1;
    AListItem.ImageIndex := AIndex;
    // get extensions file info
    if SHGetFileInfo( PChar( '*' + AExtension ), FILE_ATTRIBUTE_NORMAL, Info, SizeOf( Info ),
      SHGFI_TYPENAME or SHGFI_USEFILEATTRIBUTES ) then
        AFileType := AFileInfo.szTypeName;
    end;
    
        5
  •  1
  •   Bruce McGee    17 年前

    听起来不是油嘴滑舌,但谷歌是你的朋友。以下是“delphi关联图标”的几个初步结果:

    http://www.delphi3000.com/articles/article_453.asp?SK=

    http://www.jpgriffiths.com/tutorial/Snippets%5Cgetassociatedicon.html

        6
  •  0
  •   skamradt    17 年前

    另一种方法是在注册表中的HKEY_CLASSES_ROOT下查找扩展名,然后按照默认值(如果可用)中的键进行操作,其默认值是描述。在第二级中,您还可以获取要打开的shell命令,或打印文件类型以及默认图标的路径。