包 含 在 可 执 行 模 块 中 的 图 标 资 源 是 以 二 进 制 数 据( 或 称, 资 源) 的 形 式 存 储 的, 因 而, 我 们 应 该 把 这 些 二 进 制 数 据 转 换 成 图 标 文 件 的 格 式, 然 后 再 存 为 图 标 文 件(*.ICO)。 因 为 有 了Inprise Corporation ( 原Borland International) 的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)。
unit Unit1;
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;
procedure Button1Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure N2Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
Form1: TForm1;
Total,// 文 件 中 图 标 的 总 数
No:Integer;// 当 前 图 标 在 原 文 件 中 的 序 号
Path,// 程 序 所 在 的 路 径
ModuleName:String;// 从 哪 个 文 件 提 取 图 标
implementation
{$R *.DFM}
procedure TForm1.Button1Click(Sender: TObject);
// 该 事 件 句 柄 被Button1 和Button2 所 共 享
//Button1 和Button2 的Caption
分 别 是" 向 前 浏 览" 和" 向 后 浏 览"
//Button1 和Button2 的Tag 分 别 是1 和-1
begin
if Total=0 then
Exit;
No:=No+(Sender as TButton).tag;
if No>Total then
No:=0;
if No<0 then
No:=Total;
Image1.Picture.Icon:=nil;
Image1.Picture.Icon.Handle:
=ExtractIcon(hInstance,PChar(ModuleName),No);
Label1.Caption:='No.'+IntToStr(No)+' icon';
//Label1 用 于 指 示 当 前 图 标 在 原 文 件 中 的 序 号
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Path:=ExtractFilePath(Application.ExeName);
// 下 面 的 代 码 使 程 序 有 处 理 命 令 行 参 数 的 能 力
if ParamCount>0
then
begin
ModuleName:=ParamStr(1);
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
Form1.caption:=IntToStr(Total)
+' icon(s) found in '+ParamStr(1);
end;
end;
procedure TForm1.Button3Click(Sender: TObject);
// 这 段 代 码 保 存 当 前 图 标
begin
If Total=0 then
Exit;
Image1.Picture.Icon.SaveToFile
(Path+'/Icon'+IntToStr(No)+'.ico');
{ 把 图 标 文 件 与 该 程 序 存 于
同 一 目 录, 文 件 名 为"Icon" 加 序 号 的 形 式}
end;
procedure TForm1.N2Click(Sender: TObject);
// 这 段 代 码 从 菜 单 中 选 择 一 个 文 件
begin
If OpenDialog1.Execute
then
begin
ModuleName:=OpenDialog1.FileName;
Total:=ExtractIcon(hInstance,PChar(ModuleName),-1);
No:=0;
Label1.Caption :='';
Form1.Caption:=IntToStr(Total)+' icon(s) found in '+ModuleName;
end;
end;
end.
( 调 试 环 境:Delphi 4.0 , Windows 95, Windows NT4)
---- 说 明:API 函 数ExtractIcon 是 在ShellAPI 单 元 中 声 明 的, 所 以 你 必 须 在Uses 语 句 中 加 入 此 单 元 才 能 使 用 该 函 数。 它 在Delphi 中 的 原 型 声 明 如 下:
---- function ExtractIcon(hInst: HINST;
lpszExeFileName: PChar;
nIconIndex: UINT): HICON;
stdcall;
---- 参 数 说 明:
---- hInst: 为 调 用 该 函 数 的 实 例 句 柄;
---- lpszExeFileName: 指 明 从 哪 个 文 件 提 取 图 标( 不 一 定 非 得 是EXE 文 件);
---- nIconIndex: 该 参 数 为 负1 时, 函 数 返 回 指 定 文 件 中 包 含 的 图 标 个 数; 否 则, 返 回 序 号 为nIconIndex 的 图 标( 如 果 存 在 的 话) 的 句 柄。 在 文 件 中 图 标 的 序 号 是 从0 开 始 的 。
---- 如 果 函 数 调 用 失 败 则 返 回0.