更多有关资源的问题参考API应用相关篇章
资源文件(*.res)通过编译指令 $R 关联, 譬如工程文件 Project1 中的 {$R *.res} 就是关联 Project1.res 资源文件, 我们直接写作 {$R Project1.res} 不会有问题(但如果工程文件改名时, 你也得随着改才行). 譬如:
program Project1; uses Forms, Unit1 in 'Unit1.pas' {Form1}; {$R Project1.res} begin Application.Initialize; Application.MainFormOnTaskbar := True; Application.CreateForm(TForm1, Form1); Application.Run; end.
这个资源文件中至少包含着文件图标, 假如我们删除 {$R *.res} 后编译, 看前后对比图:
这时我们可以通过代码, 调用其他图标:
procedure TForm1.FormCreate(Sender: TObject); begin Application.Icon.LoadFromFile('c:/temp/my.ico'); end;
这样还是不好, 如果运行程序的电脑没有这个文件呢? 最好让程序携带着它, 这就要通过资源文件. 让我们从头来过:
1、新建一个 VCL Forms Application; 并 Save All;
2、并通过菜单 Project → View Souse 打开工程源文件;
3、删除 {$R *.res}
4、如图新建一个 Text 文件
5、文件编辑如下:
MainIcon ICON "c:/temp/my.ico"
注意: 其中的 c:/temp/my.ico 可以随便定义, 但文件必须存在; 另外其中的所有大小写无关, 路径两边的双引号也可以省略.
6、把它保存为: Project1.rc ; 注意要保存在程序相同目录, 文件名和工程文件名相同, 后缀是 rc
7、如图把 Project1.rc 添加到工程组:
8、这时工程文件自动添加了一行: {$R 'Project1.res' 'Project1.rc'}
9、好了, 编译执行程序, 如图:
注释:
1、*.rc 文件算是资源文件(*.res) 的源文件, 在程序编译过程中会编译成同名的 res 文件;
2、上面的例子是个特例, 一般我们不能使用和工程同名的资源文件;
3、MainIcon ICON "c:/temp/my.ico" 中的 ICON 说明这是一个图标资源, MainIcon 是该资源的标识符, 这个标识符应该是可以自定义的, 不过在这个特例中, 只能使用 MainIcon , 因为程序要从同名的资源文件中查找标识为 MainIcon 的资源做图标.
现在要做一个携带两个图标的资源文件, 并调用的例子.
1、首先建新工程, 保存, 注意这次我们不删除 {$R *.res}
2、复制两个 ico 文件到工程目录, 譬如文件是: IcoFile_1.ico、IcoFile_2.ico
3、建立文本文件输入:
ico1 ICON IcoFile_1.ico
ico2 ICON IcoFile_2.ico
然后保存为: MyRes.rc, 并 Add 到工程中, 如图:
4、此时的工程文件会自动插入: {$R 'MyRes.res' 'MyRes.rc'}
5、添加四个按钮, 实现代码如下:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; Button3: TButton; Button4: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure Button3Click(Sender: TObject); procedure Button4Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} //使用资源中的第一个自定义图标 procedure TForm1.Button1Click(Sender: TObject); begin Application.Icon.Handle := LoadIcon(HInstance, 'ico1'); { HInstance 当前程序实例的句柄, 调用资源文件一定要用到它; ico1 是资源文件的标识符; LoadIcon 是个 API 函数, 专门用于调用资源中的 ico 文件, 它返回的是指定 ico 文件的句柄. } end; //使用资源中的第二个自定义图标 procedure TForm1.Button2Click(Sender: TObject); begin Application.Icon.Handle := LoadIcon(HInstance, 'ico2'); end; //使用资源中默认的程序图标 procedure TForm1.Button3Click(Sender: TObject); begin Application.Icon.Handle := LoadIcon(HInstance, 'MainIcon'); end; //不使用图标(会显示 Windows 系统的默认图标) procedure TForm1.Button4Click(Sender: TObject); begin Application.Icon := nil; end; end. //效果图:
注释:
1、此时的 MyRes.rc 被编译成了 MyRes.res;
2、此时的 IcoFile_1.ico、IcoFile_2.ico 文件被编译进 MyRes.res;
3、此时的 MyRes.res 文件也被编译到 Project1.exe 中了.
学习使用资源文件[3] - 用 Image 显示资源中的图片
首先编辑 rc 文件如下(假定图片文件放在程序目录下的 img 文件夹下):
bmp1 BITMAP img/bmpFile1.bmp
bmp2 BITMAP img/bmpFile2.bmp
或者:
bmp1,BITMAP,img/bmpFile1.bmp
bmp2,BITMAP,img/bmpFile2.bmp
然后在窗体上添加一个 Image、两个 Button, 代码如下:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, StdCtrls; type TForm1 = class(TForm) Image1: TImage; Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Image1.AutoSize := True; end; procedure TForm1.Button1Click(Sender: TObject); begin Image1.Picture.Bitmap.Handle := LoadBitmap(HInstance, 'bmp1'); end; procedure TForm1.Button2Click(Sender: TObject); begin image1.Picture.Bitmap.LoadFromResourceName(HInstance, 'bmp2'); end; end. //效果图:
学习使用资源文件[4] - 用资源中的图片做背景、使用 LoadFromResourceID
首先编辑 rc 文件如下(假定图片文件放在程序目录下的 img 文件夹下):
1 BITMAP img/bmpFile1.bmp
2 BITMAP img/bmpFile2.bmp
或者:
1,BITMAP,img/bmpFile1.bmp
2,BITMAP,img/bmpFile2.bmp
这次我们是给每个资源做了编号, 没有取标识名称; 然后在窗体上添加两个 Button, 代码如下:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure FormCreate(Sender: TObject); procedure Button1Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} var bit: TBitmap; procedure TForm1.FormCreate(Sender: TObject); begin bit := TBitmap.Create; end; //对只有编号的图片资源需要用 LoadFromResourceID 调用 procedure TForm1.Button1Click(Sender: TObject); begin bit := TBitmap.Create; bit.LoadFromResourceID(HInstance, 1); Self.Brush.Bitmap := bit; Repaint; end; procedure TForm1.Button2Click(Sender: TObject); begin bit := TBitmap.Create; bit.LoadFromResourceID(HInstance, 2); Self.Brush.Bitmap := bit; Repaint; end; procedure TForm1.FormDestroy(Sender: TObject); begin bit.Free; end; end. //效果图:
//rc 文件: cur1 CURSOR cur/kyodai.cur cur2 CURSOR cur/static.cur //或者 cur1,CURSOR,cur/kyodai.cur cur2,CURSOR,cur/static.cur //程序代码: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls; type TForm1 = class(TForm) Panel1: TPanel; Panel2: TPanel; procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Screen.Cursors[1] := LoadCursor(HInstance, 'cur1'); Screen.Cursors[2] := LoadCursor(HInstance, 'cur2'); Panel1.Cursor := TCursor(1); //Panel1.Cursor := 1; 也可, 因为 TCursor 就是个数字类型. Panel2.Cursor := TCursor(2); end; end. //效果图:
//rc 文件:MyMenu1 MENUbeginPopup "File"beginMenuItem "&Open"MenuItem "&Save"MenuItem SeparatorMenuItem "E&xit"endend{严格的头可能是这样写: MyMenu1 MENU PRELOAD DISCARDABLE}
//程序代码: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, Menus, StdCtrls; type TForm1 = class(TForm) procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); var hm: HMENU; begin hm := LoadMenu(HInstance, 'MyMenu1'); SetMenu(Handle, hm); end; end. //效果图:
//rc 文件:StringTablebegin0 "AAAA"1 "BBBB"2 "CCCC"3 "DDDD"end//也可以这样写:StringTablebegin0,"AAAA"1,"BBBB"2,"CCCC"3,"DDDD"end//还可以这样写:StringTable{0,"AAAA"1,"BBBB"2,"CCCC"3,"DDDD"}{严格的头可能是这样写: STRINGTABLE DISCARDABLE}
//程序代码: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Memo1: TMemo; procedure FormCreate(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin Memo1.Clear; with Memo1.Lines do begin Add(LoadStr(0)); Add(LoadStr(1)); Add(LoadStr(2)); Add(LoadStr(3)); end; end; end. //效果图:
//rc 文件: sound1 WAVE "SoundFile1.wav" sound2 WAVE "SoundFile2.wav" //代码: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} uses MMSystem; {下面用到的 sndPlaySound、PlaySound 都是在此单元声明的} procedure TForm1.Button1Click(Sender: TObject); var rs: TResourceStream; begin rs := TResourceStream.Create(HInstance, 'sound1', 'WAVE'); sndPlaySound(rs.Memory, SND_ASYNC or SND_MEMORY); rs.Free; end; procedure TForm1.Button2Click(Sender: TObject); var rs: TResourceStream; begin rs := TResourceStream.Create(HInstance, 'sound2', 'WAVE'); PlaySound(rs.Memory, HInstance, SND_ASYNC or SND_MEMORY); rs.Free; end; end.
//下面是 Windows 支持的资源格式: RT_CURSOR = MakeIntResource(1); RT_BITMAP = MakeIntResource(2); RT_ICON = MakeIntResource(3); RT_MENU = MakeIntResource(4); RT_DIALOG = MakeIntResource(5); RT_STRING = MakeIntResource(6); RT_FONTDIR = MakeIntResource(7); RT_FONT = MakeIntResource(8); RT_ACCELERATOR = MakeIntResource(9); RT_RCDATA = Types.RT_RCDATA; //MakeIntResource(10); RT_MESSAGETABLE = MakeIntResource(11); DIFFERENCE = 11; RT_GROUP_CURSOR = MakeIntResource(DWORD(RT_CURSOR + DIFFERENCE)); RT_GROUP_ICON = MakeIntResource(DWORD(RT_ICON + DIFFERENCE)); RT_VERSION = MakeIntResource(16); RT_DLGINCLUDE = MakeIntResource(17); RT_PLUGPLAY = MakeIntResource(19); RT_VXD = MakeIntResource(20); RT_ANICURSOR = MakeIntResource(21); RT_ANIICON = MakeIntResource(22); //尽管 Windows 规定 RCDATA 用作自定义格式, 我们也可以自定义格式名称, 譬如本例(rc 文件): MyFile1 RCDATA "c:/Windows/system32/notepad.exe" MyFile2 MyRes "c:/Windows/System32/calc.exe" {上面把 notepad.exe 时指定为 RCDATA 格式; 把 calc.exe 就指定成了自定义的 MyRes 格式} //本例在资源中嵌入了记事本和计算器, 然后提取并调用: unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TForm1 = class(TForm) Button1: TButton; Button2: TButton; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Button1Click(Sender: TObject); var rs: TResourceStream; begin rs := TResourceStream.Create(HInstance, 'MyFile1', RT_RCDATA); rs.SaveToFile('c:/temp/pad.exe'); WinExec('c:/temp/pad.exe', 1); rs.Free; end; procedure TForm1.Button2Click(Sender: TObject); var rs: TResourceStream; begin rs := TResourceStream.Create(HInstance, 'MyFile2', 'MyRes'); rs.SaveToFile('c:/temp/sum.exe'); WinExec('c:/temp/sum.exe', 1); rs.Free; end; end.
本例将把一张 bmp 图片, 以资源文件的方式嵌入 dll, 然后再调用.
第一步: 建一个 DLL 工程, 如图:
然后保存, 我这里使用的名称都是默认的.
第二步: 建一个资源原文件, 如图:
编辑内容如下(路径中的文件一定要存在):
img1 BITMAP "c:/temp/test.bmp"
然后, 取个名(后缀须是 rc, 我这里取名为 Res.rc), 保存在工程目录下.
第三步: 在 DLL 工程中添加这个资源原文件, 如图:
此时, 工程源文件中会添加一句: {$R 'Res.res' 'Res.rc'}, 我们需要的源文件这样即可:
library Project1;
{$R 'Res.res' 'Res.rc'}
begin
end.
然后 Ctrl+F9 编译; 此时在工程目录下会生成我们需要的 Project1.dll.
第四步: 把刚才的 Project1.dll 文件复制到 c:/temp 下.
这样过会我们可以通过 c:/temp/Project1.dll 找到这个文件. 至此 DLL 制作完毕.
第五步: 重新建一个 VCL Forms Application 工程, 代码如下:
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs; type TForm1 = class(TForm) procedure FormPaint(Sender: TObject); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormPaint(Sender: TObject); var h: THandle; bit: TBitmap; begin h := LoadLibrary('c:/temp/Project1.dll'); {载入 DLL} bit := TBitmap.Create; bit.LoadFromResourceName(h, 'img1'); {提取资源} Canvas.Draw(10, 10, bit); {在窗体上绘制图片} FreeLibrary(h); {载卸 DLL} bit.Free; end; end. //效果图: