windows 如何使用 Delphi 从文件扩展名中获取图标和描述?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/829843/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to get icon and description from file extension using Delphi?
提问by Pauk
Basically I have a TcxGrid which will be listing various files names and I'd like to give further details based on the file extension, specifically it's description (e.g. for .PDF it's "Adobe Acrobat Document") and it's related icon.
基本上我有一个 TcxGrid,它将列出各种文件名,我想根据文件扩展名提供更多详细信息,特别是它的描述(例如,对于 .PDF,它是“Adobe Acrobat 文档”)及其相关图标。
I notice there is a very similar question alreadybut it's C# related and I'd like something Delphi based.
我注意到已经有一个非常相似的问题,但它与 C# 相关,我想要一些基于 Delphi 的东西。
Suggestions on where to look for this kind of info would be good and if there is a class similar to the one mentioned in the C# post above (obviously in Delphi) that would be great.
关于在哪里寻找此类信息的建议会很好,如果有一个类似于上面 C# 帖子中提到的类(显然是在 Delphi 中),那就太好了。
回答by Pauk
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.
感谢 Rob Kennedy 为我指出 ShGetFileInfo 的方向。然后我在谷歌上搜索并找到了这两个示例 - Delphi 3000和Torry 的. 从那以后,我编写了以下课程来做我需要的事情。
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.
此外,就在我完成时,比尔米勒的回答给了我最后一点我需要的帮助。最初,我将完整的文件名传递给 ShGetFileInfo,这并不是我想要的。建议通过“*.EXT”的调整很棒。
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.
最后,在我使用的内容中,我将其切换为使用 TcxImageList 而不是 TImageList,因为我遇到了图标上出现黑色边框的问题,因为这是一个快速修复。
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.
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.
这里还有一个使用它的示例测试应用程序,它非常简单,只是一个带有 TPageControl 的表单。我的实际用途不是用于此,而是用于 TcxGrid 中的 Developer Express TcxImageComboxBox。
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.
Thanks everyone for your answers!
谢谢大家的回答!
回答by Rob Kennedy
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.
打电话ShGetFileInfo
。它可以告诉您描述(该函数词汇中的“类型名称”),并且可以为您提供图标句柄,或系统图像列表的句柄,图标所在的位置,或保存模块的路径图片资源。该函数可以做很多不同的事情,所以一定要仔细阅读文档。
MSDN saysShGetFileInfo
"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.
MSDN 表示ShGetFileInfo
“可能会很慢”,并称该IExtractIcon
接口为“更灵活和高效”的替代方案。但它推荐的顺序是使用一个IShellFolder
接口,然后调用GetUIObjectOf
获取文件的IExtractIcon
接口,然后调用GetIconLocation
和Extract
在它上检索图标的句柄。
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.
据我所知,ShGetFileInfo
无论如何,这确实是这样做的,但它要麻烦得多,而且在您完成所有这些之后,您仍然没有文件的类型描述。坚持ShGetFileInfo
直到速度和效率成为一个明显的问题。
回答by Bill Miller
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;
回答by Bill Miller
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;
回答by Bruce McGee
Not to sound glib, but Google is your friend. Here are a couple of the first results for "delphi associated icon":
不要听起来油腔滑调,但谷歌是你的朋友。以下是“delphi 相关图标”的几个初步结果:
http://www.delphi3000.com/articles/article_453.asp?SK=
http://www.delphi3000.com/articles/article_453.asp?SK=
http://www.jpgriffiths.com/tutorial/Snippets%5Cgetassociatedicon.html
http://www.jpgriffiths.com/tutorial/Snippets%5Cget associatedicon.html
回答by skamradt
The other method is to hunt down the extension in the registry under HKEY_CLASSES_ROOT, then follow the key in the default value (if available) and its default is the description. This second level is also where you can get the shell commands to open, or print the file type as well as the path to the default icon.
另一种方法是在注册表中的 HKEY_CLASSES_ROOT 下寻找扩展名,然后按照默认值(如果可用)中的键,其默认值是描述。第二级也是您可以打开 shell 命令的地方,或者打印文件类型以及默认图标的路径。
回答by Bob S
Here are a couple good examples of using ShGetFileInfo from bitwisemag.com:
以下是使用来自 bitwisemag.com 的 ShGetFileInfo 的几个很好的例子:
http://www.bitwisemag.com/copy/delphi/lpad1.html
http://www.bitwisemag.com/copy/delphi/lpad1.html