372 lines
11 KiB
ObjectPascal
372 lines
11 KiB
ObjectPascal
{-----------------------------------------------------------------------------
|
|
The contents of this file are subject to the Mozilla Public License
|
|
Version 1.1 (the "License"); you may not use this file except in compliance
|
|
with the License. You may obtain a copy of the License at
|
|
http://www.mozilla.org/MPL/MPL-1.1.html
|
|
|
|
Software distributed under the License is distributed on an "AS IS" basis,
|
|
WITHOUT WARRANTY OF ANY KIND, either expressed or implied. See the License for
|
|
the specific language governing rights and limitations under the License.
|
|
|
|
The Original Code is: JvFileInfo.PAS, released on 2002-05-26.
|
|
|
|
The Initial Developer of the Original Code is Peter Thörnqvist [peter3 att users dott sourceforge dott net]
|
|
Portions created by Peter Thörnqvist are Copyright (C) 2002 Peter Thörnqvist.
|
|
All Rights Reserved.
|
|
|
|
Contributor(s):
|
|
|
|
Last Modified: 2002-05-26
|
|
|
|
You may retrieve the latest version of this file at the Project JEDI's JVCL home page,
|
|
located at http://jvcl.sourceforge.net
|
|
|
|
Known Issues:
|
|
-----------------------------------------------------------------------------}
|
|
|
|
{$I JVCL.INC}
|
|
|
|
{Provides an interface to most of what is returned by the ShGetFileInfo function
|
|
to allow easier access to information about a files type, attributes, icon
|
|
image and icon handle. Most of the file info functions can be called with a
|
|
non-existent file to return "generic" info about a specific file type. }
|
|
|
|
unit JvFileInfo;
|
|
|
|
interface
|
|
|
|
uses
|
|
Windows, SysUtils, Classes, Graphics, Controls,
|
|
ShellAPI,
|
|
JvComponent, JvTypes;
|
|
|
|
type
|
|
TJvExeType = (etNone, etMSDos, etWin16, etWin32, etConsole);
|
|
TJvIconModifier = (imNormal, imOverlay, imSelected, imOpen, imShellSize, imSmall);
|
|
|
|
TJvFileInfo = class(TJvComponent)
|
|
private
|
|
FLargeImages: TImageList;
|
|
FSmallImages: TImageList;
|
|
FFileName: TFileName;
|
|
FModifier: TJvIconModifier;
|
|
FIcon: TIcon;
|
|
function GetSmallImages: TImageList;
|
|
function GetLargeImages: TImageList;
|
|
procedure SetIcon(const Value: TIcon);
|
|
protected
|
|
FIntDummy: Integer;
|
|
FStrDummy: string;
|
|
FExeDummy: TJvExeType;
|
|
FHandleDummy: THandle;
|
|
function GetIconIndex: Integer;
|
|
function GetDisplayName: string;
|
|
function GeTJvExeType: TJvExeType;
|
|
function GetAttributes: Integer;
|
|
function GetIconLocation: string;
|
|
function GetTypeString: string;
|
|
function GetIconHandle: THandle;
|
|
function GetAttrString: string;
|
|
procedure SetFileName(Value: TFileName);
|
|
procedure SetModifier(Value: TJvIconModifier);
|
|
public
|
|
property LargeImages: TImageList read FLargeImages;
|
|
property SmallImages: TImageList read FSmallImages;
|
|
property IconHandle: THandle read GetIconHandle stored False;
|
|
property Attributes: Integer read GetAttributes stored False;
|
|
function GetCustomInformation(Value: string): TJvFileInfoRec;
|
|
published
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
property FileName: TFileName read FFileName write SetFileName stored False;
|
|
property Modifier: TJvIconModifier read FModifier write SetModifier default imNormal;
|
|
property IconIndex: Integer read GetIconIndex write FIntDummy stored False;
|
|
property DisplayName: string read GetDisplayName write FStrDummy stored False;
|
|
property ExeType: TJvExeType read GeTJvExeType write FExeDummy stored False;
|
|
property AttrString: string read GetAttrString write FStrDummy stored False;
|
|
property IconLocation: string read GetIconLocation write FStrDummy stored False;
|
|
property TypeString: string read GetTypeString write FStrDummy stored False;
|
|
property Icon: TIcon read FIcon write SetIcon stored False;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
Registry;
|
|
|
|
constructor TJvFileInfo.Create(AOwner: TComponent);
|
|
begin
|
|
inherited Create(AOwner);
|
|
FIcon := TIcon.Create;
|
|
if not (csDesigning in ComponentState) then
|
|
begin
|
|
GetLargeImages;
|
|
GetSmallImages;
|
|
end;
|
|
SetFileName(FFileName);
|
|
end;
|
|
|
|
destructor TJvFileInfo.Destroy;
|
|
begin
|
|
FLargeImages.Free;
|
|
FSmallImages.Free;
|
|
FIcon.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TJvFileInfo.GetLargeImages: TImageList;
|
|
var
|
|
SysIL: THandle;
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
if not Assigned(FLargeImages) then
|
|
FLargeImages := TImageList.Create(Self);
|
|
SysIL := SHGetFileInfo('', 0, Sfi, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_LARGEICON);
|
|
if SysIL <> 0 then
|
|
FLargeImages.Handle := SysIL;
|
|
FLargeImages.ShareImages := True;
|
|
Result := FLargeImages;
|
|
end;
|
|
|
|
function TJvFileInfo.GetSmallImages: TImageList;
|
|
var
|
|
SysIL: THandle;
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
if not Assigned(FSmallImages) then
|
|
FSmallImages := TImageList.Create(Self);
|
|
SysIL := SHGetFileInfo('', 0, Sfi, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX or SHGFI_SMALLICON);
|
|
if SysIL <> 0 then
|
|
FSmallImages.Handle := SysIL;
|
|
FSmallImages.ShareImages := True;
|
|
Result := FSmallImages;
|
|
end;
|
|
|
|
procedure TJvFileInfo.SetModifier(Value: TJvIconModifier);
|
|
begin
|
|
FModifier := Value;
|
|
GetIconHandle;
|
|
end;
|
|
|
|
procedure TJvFileInfo.SetFileName(Value: TFileName);
|
|
begin
|
|
FFileName := Value;
|
|
GetIconHandle;
|
|
end;
|
|
|
|
{ returns index of icon for filename in the systemlist }
|
|
|
|
function TJvFileInfo.GetIconIndex: Integer;
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_SYSICONINDEX);
|
|
Result := Sfi.iIcon;
|
|
end;
|
|
|
|
function TJvFileInfo.GetDisplayName: string;
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_DISPLAYNAME);
|
|
Result := Sfi.szDisplayName;
|
|
end;
|
|
|
|
function TJvFileInfo.GeTJvExeType: TJvExeType;
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
Res: Integer; // sLo,sHi:string;
|
|
begin
|
|
Result := etNone;
|
|
Res := SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_EXETYPE);
|
|
if Res = 0 then
|
|
Exit;
|
|
case Lo(Res) of
|
|
77:
|
|
Result := etMSDos;
|
|
78:
|
|
Result := etWin16;
|
|
80:
|
|
Result := etWin32;
|
|
else
|
|
Result := etConsole; { ? }
|
|
end;
|
|
end;
|
|
|
|
function TJvFileInfo.GetAttributes: Integer;
|
|
// var Sfi: TSHFileInfo;
|
|
begin
|
|
{ this doesn't work, use "old" method instead }
|
|
{
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_ATTRIBUTES);
|
|
Result := Sfi.dwAttributes;}
|
|
Result := GetFileAttributes(PChar(FFileName));
|
|
end;
|
|
|
|
function TJvFileInfo.GetAttrString: string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
I := GetAttributes;
|
|
Result := '';
|
|
if (I and FILE_ATTRIBUTE_NORMAL) <> 0 then
|
|
Exit; { no attributes }
|
|
if (I and FILE_ATTRIBUTE_ARCHIVE) <> 0 then
|
|
Result := Result + 'A';
|
|
if (I and FILE_ATTRIBUTE_COMPRESSED) <> 0 then
|
|
Result := Result + 'C';
|
|
if (I and FILE_ATTRIBUTE_DIRECTORY) <> 0 then
|
|
Result := Result + 'D';
|
|
if (I and FILE_ATTRIBUTE_HIDDEN) <> 0 then
|
|
Result := Result + 'H';
|
|
if (I and FILE_ATTRIBUTE_READONLY) <> 0 then
|
|
Result := Result + 'R';
|
|
if (I and FILE_ATTRIBUTE_SYSTEM) <> 0 then
|
|
Result := Result + 'S';
|
|
end;
|
|
|
|
function StrTrimAll(const S: string; const Chars: TSysCharSet): string;
|
|
var
|
|
I: Integer;
|
|
begin
|
|
for I := 1 to Length(S) do
|
|
if not (S[I] in Chars) then
|
|
Result := Result + S[I];
|
|
end;
|
|
|
|
function AddDot(S: string): string;
|
|
begin
|
|
Result := S;
|
|
if (Length(Result) > 0) and (Result[1] <> '.') then
|
|
Result := '.' + Result;
|
|
end;
|
|
|
|
function ExpandEnvVar(const Value: string): string;
|
|
var
|
|
Dest: array [0..MAX_PATH] of Char;
|
|
begin
|
|
ExpandEnvironmentStrings(PChar(Value), Dest, MAX_PATH - 1);
|
|
Result := Dest;
|
|
end;
|
|
|
|
function GetAdvancedIconLocation(const FileName: string; var iIcon: Integer): string;
|
|
var
|
|
Reg: TRegistry;
|
|
Ext, sPath, Tmp: string;
|
|
I: Integer;
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
// first try the easy way:
|
|
SHGetFileInfo(PChar(FileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_ICON or SHGFI_ICONLOCATION);
|
|
Result := Sfi.szDisplayName;
|
|
if Result <> '' then
|
|
begin
|
|
iIcon := Sfi.iIcon;
|
|
Exit;
|
|
end;
|
|
|
|
if Pos('.', FileName) > 0 then
|
|
Ext := ExtractFileExt(StrTrimAll(FileName, ['"', '''']))
|
|
else
|
|
Ext := AddDot(FileName);
|
|
|
|
if Length(Ext) = 0 then
|
|
Exit;
|
|
Reg := TRegistry.Create;
|
|
try
|
|
Reg.RootKey := HKEY_CLASSES_ROOT;
|
|
// is the key present ?
|
|
if Reg.OpenKey(Ext, False) then
|
|
// get ID to associated program:
|
|
Result := Reg.ReadString('');
|
|
if Reg.OpenKey('\' + Result + '\DefaultIcon', False) then
|
|
Result := Reg.ReadString(''); // path (and possibly index) to icon location
|
|
if Length(Result) > 0 then
|
|
begin
|
|
if Pos('%1', Result) > 0 then
|
|
Result := FileName; // instance specific icon
|
|
I := Pos(',', Result);
|
|
sPath := '';
|
|
if I > 0 then
|
|
begin
|
|
sPath := Copy(Result, I + 1, MaxInt);
|
|
Result := Copy(Result, 1, I - 1);
|
|
end;
|
|
Tmp := '';
|
|
for I := 1 to Length(sPath) do
|
|
if not (sPath[I] in ['-', '0'..'9']) then
|
|
Continue
|
|
else
|
|
Tmp := Tmp + sPath[I];
|
|
iIcon := Abs(StrToIntDef(Tmp, 0)); // convert to positive index
|
|
end
|
|
finally
|
|
Reg.Free;
|
|
end;
|
|
Result := ExpandEnvVar(Result); // replace any environment variables in path (like %systemroot%)
|
|
end;
|
|
|
|
function TJvFileInfo.GetIconLocation: string;
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
iIcon: Integer;
|
|
begin
|
|
{ this doesn't seem to work on files, only on directories (always returns an empty string)... }
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_ICONLOCATION);
|
|
Result := Sfi.szDisplayName;
|
|
if Result = '' then
|
|
Result := StrTrimAll(GetAdvancedIconLocation(FFileName, iIcon), ['"']);
|
|
end;
|
|
|
|
function TJvFileInfo.GetTypeString: string;
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo), SHGFI_TYPENAME);
|
|
Result := Sfi.szTypeName;
|
|
if Result = '' then
|
|
Result := AnsiUpperCase(Copy(ExtractFileExt(FFileName), 2, MaxInt)) + ' file';
|
|
end;
|
|
|
|
function TJvFileInfo.GetIconHandle: THandle;
|
|
const
|
|
Modifier: array [TJvIconModifier] of Integer =
|
|
(0, SHGFI_LINKOVERLAY, SHGFI_SELECTED, SHGFI_OPENICON, SHGFI_SHELLICONSIZE, SHGFI_SMALLICON);
|
|
var
|
|
Sfi: TSHFileInfo;
|
|
begin
|
|
SHGetFileInfo(PChar(FFileName), 0, Sfi, SizeOf(TSHFileInfo),
|
|
SHGFI_SYSICONINDEX or SHGFI_ICON or Modifier[FModifier]);
|
|
Result := Sfi.hIcon;
|
|
FIcon.Handle := Sfi.hIcon;
|
|
end;
|
|
|
|
procedure TJvFileInfo.SetIcon(const Value: TIcon);
|
|
begin
|
|
// do nothing
|
|
end;
|
|
|
|
function TJvFileInfo.GetCustomInformation(Value: string): TJvFileInfoRec;
|
|
var
|
|
Tmp: SHFILEINFO;
|
|
Flags: Cardinal;
|
|
begin
|
|
Flags := SHGFI_ICONLOCATION;
|
|
SHGetFileInfo(PChar(Value), 0, Tmp, SizeOf(SHFILEINFO), Flags);
|
|
Result.Location := Tmp.szDisplayName;
|
|
|
|
Flags := SHGFI_DISPLAYNAME + SHGFI_ATTRIBUTES + SHGFI_TYPENAME + SHGFI_SYSICONINDEX;
|
|
SHGetFileInfo(PChar(Value), 0, Tmp, SizeOf(SHFILEINFO), Flags);
|
|
Result.DisplayName := Tmp.szDisplayName;
|
|
Result.Attributes := Tmp.dwAttributes;
|
|
Result.TypeName := Tmp.szTypeName;
|
|
Result.SysIconIndex := Tmp.iIcon;
|
|
|
|
Flags := SHGFI_EXETYPE + SHGFI_ICON;
|
|
Result.ExeType := SHGetFileInfo(PChar(Value), 0, Tmp, SizeOf(SHFILEINFO), Flags);
|
|
Result.Icon := Tmp.hIcon;
|
|
end;
|
|
|
|
end.
|
|
|