How to get icon and description from file extension using Delphi? How to get icon and description from file extension using Delphi? windows windows

How to get icon and description from file extension using Delphi?


Thanks to Rob Kennedy for pointing me in the direction of ShGetFileInfo. I then Googled on that and found these two examples - Delphi 3000, Torry's. From that I wrote the following class to do what I needed.

Also, just as I was finishing up Bill Miller's answer gave me the final bit of help I needed. Originally I was passing full file names through to ShGetFileInfo, which wasn't ideally what I wanted. The tweak suggested of passing "*.EXT" was great.

The class could do with more work but it does what I need. It seems to handle file extensions that have no details associated either.

Finally, in what I'm using I've switched it to using a TcxImageList instead of a TImageList, since I was having problems with black borders appearing on the icons, because it was a quick fix.

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.}interfaceuses 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;implementationuses 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.

Also here is an example test app using it, it's very simple, just a form with a TPageControl on it. My actual use was not for this, but for with a Developer Express TcxImageComboxBox in a TcxGrid.

unit Main;{  Created       : 2009-05-07  Description   : Test app for TFileAssociationDetails.}interfaceuses  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.

Thanks everyone for your answers!


Call ShGetFileInfo. It can tell you the description (the "type name," in that function's vocabulary), and it can give you an icon handle, or a handle to the system image list, where the icon resides, or the path to the module that holds the image resource. That function can do lots of different things, so make sure to read the documentation carefully.

MSDN says ShGetFileInfo "may be slow" and calls the IExtractIcon interface a "more flexible and efficient" alternative. But the sequence it recommends is to use an IShellFolder interface, then call GetUIObjectOf to get the file's IExtractIcon interface, and then call GetIconLocation and Extract on it to retrieve the icon's handle.

For all I know, that's exactly what ShGetFileInfo does anyway, but it's much more cumbersome, and after you've done all that, you still wouldn't have the file's type description. Stick with ShGetFileInfo until speed and efficiency become a noticeable problem.


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;