How to get icon from a shortcut file ?
I have found that if you use a ListView component, to show a list of files in any folder that contains shortcuts, then the shortcut icons do not appear correctly -
they do not show the true icon of the application to which they relate.
However, there is a a very useful feature of SHGetFileInfo, which is SHGFI_LINKOVERLAY. This adds the shortcut "arrow", which is shown in the bottom left corner of any shortcut icon. The demo code below shows the basic use of the SHGFI_LINKOVERLAY feature. I have added code to this demo, to distingiush between shortcut and non-shortcut files - without this code, it will overlay the shortcut "arrow" irrespective of the file type.
To show the icon of a shortcut, the following code can be used as a demo:
1. Add the following components to a new project, and adjust their
properties according to the code below:
// Code for DFM file:
object Form1: TForm1
Left = 379
Top = 355
Width = 479
Height = 382
Caption = 'Get Icon from Shortcut File'
Color = clBtnFace
Font.Charset = DEFAULT_CHARSET
Font.Color = clWindowText
Font.Height = -11
Font.Name = 'MS Sans Serif'
Font.Style = []
OldCreateOrder = False
PixelsPerInch = 96
TextHeight = 13
object ListView: TListView
Left = 0
Top = 73
Width = 471
Height = 275
Align = alClient
Columns = <
item
Width = 100
end
item
Width = 100
end>
SmallImages = imgList
TabOrder = 0
ViewStyle = vsReport
end
object Panel: TPanel
Left = 0
Top = 0
Width = 471
Height = 73
Align = alTop
TabOrder = 1
object btnGetFile: TButton
Left = 16
Top = 8
Width = 75
Height = 25
Caption = 'Get file'
TabOrder = 0
OnClick = btnGetFileClick
end
object btnGetIcon: TButton
Left = 104
Top = 8
Width = 75
Height = 25
Caption = 'Get icon'
TabOrder = 1
OnClick = btnGetIconClick
end
object edFileName: TEdit
Left = 16
Top = 40
Width = 441
Height = 21
TabOrder = 2
end
end
object dlgOpen: TOpenDialog
Filter = 'Shortcut files|*.lnk|All files|*.*'
Options = [ofHideReadOnly, ofNoDereferenceLinks,
ofEnableSizing] // - this is important !
Left = 248
Top = 8
end
object imgList: TImageList
BlendColor = clWhite
BkColor = clWhite
Masked = False
ShareImages = True
Left = 216
Top = 8
end
end
// 2. Add the code to the PAS file below:
unit cdShortCutIcon;
interface
uses
SysUtils, Graphics, Forms, ShellAPI, Dialogs, ImgList,
Classes, ComCtrls, StdCtrls, ExtCtrls, Controls;
type
TForm1 = class(TForm)
dlgOpen: TOpenDialog;
ListView: TListView;
imgList: TImageList;
Panel: TPanel;
btnGetFile: TButton;
btnGetIcon: TButton;
edFileName: TEdit;
procedure btnGetFileClick(Sender: TObject);
procedure btnGetIconClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Flags: Cardinal;
implementation
{$R *.dfm}
procedure TForm1.btnGetFileClick(Sender: TObject);
begin
{ choose file to get icon from }
if dlgOpen.Execute then edFileName.Text := dlgOpen.FileName;
end;
procedure TForm1.btnGetIconClick(Sender: TObject);
var
Icon : TIcon;
ListItem : TListItem;
shInfo : TSHFileInfo;
sFileType : string;
begin
{ initialise Flags for SHGetFileInfo }
Flags := SHGFI_ICON or SHGFI_SMALLICON or SHGFI_SYSICONINDEX or SHGFI_TYPENAME;
{ initialise ListView and Icon }
ListView.SmallImages := imgList;
Icon := TIcon.Create;
try
{ Initialise ListView.Item.Add }
ListView.Items.BeginUpdate;
ListItem := listview.items.add;
{ is this a shortcut file ? }
if ExtractFileExt(dlgOpen.FileName) = '.lnk' then
Flags := Flags or SHGFI_LINKOVERLAY else Flags := Flags;
{ assign icon, adding shortcut overlay if appropriate; get details about file type }
SHGetFileInfo(PChar(edFileName.Text), 0, shInfo, SizeOf(shInfo), Flags);
sFileType := shInfo.szTypeName;
Icon.Handle := shInfo.hIcon;
{ List File name, Icon and FileType in ListView }
ListItem.Caption := ExtractFileName(edFileName.Text); { ...add filename... }
ListItem.SubItems.Add(sFileType); { ...and filetype... }
ListItem.ImageIndex := imgList.AddIcon(Icon); { ...and icon. }
finally
{..free memory on icon and clean up.}
ListView.Items.EndUpdate;
sFileType := '';
Icon.Free;
end;
end;
end.