首页 > 学院 > 开发设计 > 正文

从文件中提取图标

2019-11-18 17:36:21
字体:
来源:转载
供稿:网友
----Windows95和NT是被无数计算机用户所青睐的图形界面(GUI)操作系统。我们知道,许多Win95或NT下的32位应用程序都带有图标(一般来说至少有一个),此外其它一些可执行模块也常常是图标的宝库。这些可执行模块包括*.EXE(可执行文件),*.DLL(DynamicLinkLibrary,即,动态连接库),*.CPL(控制面板模块)等。其中,不少图标做得非常精致、漂亮,特别惹人喜欢。当然,其中大部分的图标你可能无法直接看到。因此,不少人也许希望能有一种工具可以把这些精彩的图标从那些文件中"取"出来。笔者就有过这种想法。后来,笔者自己动手写了一个程序,使用它,我现在可以随心所欲地从任何包含图标资源的文件中提取任何我所喜爱的图标,更不用说轻松地浏览文件中的所有图标了。

----大家知道,包含在可执行模块中的图标资源是以二进制数据(或称,资源)的形式存储的,因而,我们应该把这些二进制数据转换成图标文件的格式,然后再存为图标文件(*.ICO)。因为有了InPRiseCorporation(原BorlandInternational)的Delphi提供的强大的类库和可视化支持,这项工作已变得相对比较轻松了。Delphi提供了TIcon类,该类中有一个名为SaveToFile的方法,它可方便地把对象所指的二进制数据直接存储成图标格式的文件。于是,要从其它可执行模块中提取图标,我们只需把其它模块中的二进制数据"拷"到一个TIcon对象中即可(在下面的程序中使用了一个TImage构件,该构件中包含了一个TIcon对象)。那么,怎样把数据拷到TIcon对象中呢?其实,你只需把一个图标的句柄赋给TIcon对象的句柄属性,其它细节都由Delphi代我们完成。我们可以通过Windows的API函数ExtractIcon来获取其它模块中图标的句柄。下面的这个程序可以让你轻松地浏览文件中所包含的所有图标,并且可以方便地保存下你喜欢的图标(如果此文件包含有图标资源的话)。此外,该程序还可以把位图文件(*.BMP)或图元文件(Metafile)缩小成图标文件。为了让大家更轻松地阅读此程序,笔者已经使程序的代码尽可能的短小,读者可在本示例的基础上进行其它的扩充。

----向Form1上加入如下构件:

----(1)从Standard页上选取3个TButton构件,并把Button1、Button2和Button3的Caption分别改为"向前浏览"、"向后浏览"和"保存图标"。把Button1和Button2的Tag属性分别改为1和-1(负1)。让Button2跟Button1共用一个OnClick事件句柄。

----(2)从Standard页上选取一个TMainMenu构件,把第一个菜单项(缺省名为N1)的Caption改为"文件",再把它下面的菜单项(N2)的Caption改为"打开文件"。

----(3)从Standard页上选取一个TLabel

----(4)从Additional页上选取一个TImage

----(5)从Dialogs页上选取一个TOpenDialog,并把它的Options属性的ofNoReadOnlyReturn子属性改为False。

----(6)将Form1的Font改成System字体

----(7)在Unit1的Interface部分的Uses语句中加入ShellAPI单元(以便使用API函数ExtractIcon)。

unitUnit1;
interface
uses
Windows,Messages,SysUtils,Classes,
Graphics,Controls,Forms,Dialogs,
Menus,StdCtrls,ExtCtrls,ShellAPI;
type
TForm1=class(TForm)
Image1:TImage;
Button1:TButton;
Button2:TButton;
Button3:TButton;
MainMenu1:TMainMenu;
N1:TMenuItem;
N2:TMenuItem;
Label1:TLabel;
OpenDialog1:TOpenDialog;
procedureButton1Click(Sender:TObject);
procedureFormCreate(Sender:TObject);
procedureButton3Click(Sender:TObject);
procedureN2Click(Sender:TObject);
private
{Privatedeclarations}
public
{Publicdeclarations}
end;

var
Form1:TForm1;
Total,//文件中图标的总数
No:Integer;//当前图标在原文件中的序号
Path,//程序所在的路径
ModuleName:String;//从哪个文件提取图标

implementation
{$R*.DFM}
procedureTForm1.Button1Click(Sender:TObject);
//该事件句柄被Button1和Button2所共享
//Button1和Button2的Caption
分别是"向前浏览"和"向后浏览"
//Button1和Button2的Tag分别是1和-1
begin
ifTotal=0ThenExit;
No:=No (SenderasTButton).tag;
ifNo>TotalthenNo:=0;
ifNo<0thenNo:=Total;
Image1.Picture.Icon:=nil;
Image1.Picture.Icon.Handle:
=ExtractIcon(hInstance,PChar(ModuleName),No);
Label1.Caption:='No.' IntToStr(No) 'icon';
//Label1用于指示当前图标在原文件中的序号
end;

procedureTForm1.FormCreate(Sender:TObject);
begin
Path:=ExtractFilePath(application.ExeName);
//下面的代码使程序有处理命令行参数的能力
ifParamCount>0
Thenbegin
ModuleName:=ParamStr(1);
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
Form1.caption:=IntToStr(Total)
'icon(s)foundin' ParamStr(1);
end;
end;

procedureTForm1.Button3Click(Sender:TObject);
//这段代码保存当前图标
begin
IfTotal=0ThenExit;
Image1.Picture.Icon.SaveToFile
(Path '/Icon' IntToStr(No) '.ico');
{把图标文件与该程序存于
同一目录,文件名为"Icon"加序号的形式}
end;

procedureTForm1.N2Click(Sender:TObject);
//这段代码从菜单中选择一个文件
begin
IfOpenDialog1.Execute
thenbegin
ModuleName:=OpenDialog1.FileName;
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
No:=0;Label1.Caption:='';
Form1.Caption:=IntToStr(Total) 'icon(s)foundin' ModuleName;
end;
end;
end.

(调试环境:Delphi4.0,Windows95,WindowsNT4)

----说明:API函数ExtractIcon是在ShellAPI单元中声明的,所以你必须在Uses语句中加入此单元才能使用该函数。它在Delphi中的原型声明如下:

----functionExtractIcon(hInst:HINST;lpszExeFileName:PChar;nIconIndex:UINT):HICON;stdcall;

----参数说明:

----hInst:为调用该函数的实例句柄;

----lpszExeFileName:指明从哪个文件提取图标(不一定非得是EXE文件);

----nIconIndex:该参数为负1时,函数返回指定文件中包含的图标个数;否则,返回序号为nIconIndex的图标(如果存在的话)的句柄。在文件中图标的序号是从0开始的。

----如果函数调用失败则返回0.->


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表