一初级应用篇
资源文件一般为扩展名为res的文件在VC中资源文件用得非常普遍但Delphi在其联机帮助中对资源文件没作什么介绍其实利用其自带的资源编译工具BRCCEXE(一般位于\Delphi\BIN目录下)我们完全可以做出跟VC一样效果的文件来
资源文件最大的好处是能将一些在必要时才调用的文件跟可执行文件一起编译生成一个文件这样做最大的好处就是使外部文件免遭破坏例如在一条程序中你要临时调用一幅图片一般作法是把图片放在某一路径下(通常是主程序所在路径)但如果用户路径误删你的图片文件则可能使程序找不到相应文件而出错崩溃另外如果你想自己的程序界面美观想用一些自定义光标也要用到资源文件
资源文件的使用步骤为
编写rc脚本文本
用记事本或其它文本编辑器编写一个扩展名为rc的文件例如
mycur cursor movecur //加入光标
mypic Bitmap WaterBMP //加入位图
mywav WAVE happywav //加入声音
myAVI AVI EPOENAVI //加入视频
myIco ICON CJTICO //加入图标
格式分别为在资源文件中的名称>类型>实际文件名称例如上面第一行定义一个名为mycur的光标实际名称为加入光标movecur
将rc文件编译成res资源文件
将脚本文件和实际文件拷到BrccEXE所在目录执行DOS命令格式为Brcc 脚本文件(回车)例如有一名为myfirstrc的脚本文件则执行 Brcc myfirstrc(回车)即可如果你是懒人也可新建一批处理文件内容只有一行Brcc mufistrc(因为Delphi安装后一般会在自动批处理文件中指明搜索路径的)如果编译成功则会生成一个结尾为res的文件这个文件就是我们需要的资源文件
在Delphi单元中加入资源文件
将生成的res资源文件拷贝到你所编程序的路径下在单元文件{$R *DFM}后加上一句{$R mufirstres}则将res文件加入去编译后资 源文件即已包含在可执行文件中了若你有多个资源文件也按上法依次加入
在Delphi程序中调用资源文件
资源文件在Delphi中的关键字为hinstance下面给出具体用法
<>光标的调用
首先在程序中定义一个值大于的常量因为Delphi本身用负来索引默认的光标所以我们制定的光标应从表面上开始索引然后在窗口的Oncreat事件中添加以下代码
screencursor[]:=Loadcursor (hinstancemycur);
其中为大于的常量mycur为光标在资源文件中的名字如果希望在其他控件上使用定制光标例如Panel控件只需在程序的适当处加入以下代码
Panelcursor:=;
<>位图的调用
新建一项工程添加一Timage控件在需要显示的地方写以下代码
Var mymap:Hbitmap;
begin
mymap:=LoadBitmap(hinstancemypic);
ImagepictureBitmapHandle:=mymap
end;
其中mypic为位图资源文件中的名称
〈〉AVI文件的调用
新建一工程添加一Animate控件在需要的地方加入
animaterresname:=myAVI;
animaterActive:=true;
其中myAVI为视频文件在资源文件中的名称
〈〉调用WAV文件
在uses中加入mmsystm单元以便在程序中播放WAV文件播放时Playsound(pchar(mywav)hinstancesndsync or snd_resource);其中mywav为声音文件在资源中的名称
〈〉加入光标
加入光标比较容易只要将res文件加入单元文件中即可但需注意名称最好取WWW等使第一个字母尽量靠后以免与主程序的图标顺序颠倒这样一来别人在使用你的程序时如果想选择其它图标就有很多选择了
补充
资源类型除上述类型外还可以字体文件字符串文件等
资源文件不但可以在标准图形界面下使用还可在控制台下使用
下面我们来试验一下
新建一工程将唯一的一个Form删除然后修改工程文件增加一句{$Apptype console}在uses子句中加入mmsystem并将其它引用单元删掉将Begin和end之间语句删掉至此我们就可和Turbo PASCAL下编程序一样且还可以调用windows的API和资源将资源文件{$R myfistres}加入在Begin和end之间写下
writeln(演示程序按任意键开始!);
readln;
playsound(pchar(mywav)hinstancesnd_sync or snd_resource);
writeln(演示结束!);
运行程序将弹出一个标准DOS窗口按任意键播放声音文件是不是很COOL呢!我曾下载过一个播放器在其安装目录下我发现有一DOS程序用鼠标双击它便弹出一个DOS窗口显示DOS时代特有的画图并有背景音乐!可能就是用这个方法做的
Delphi本身自带了一个叫Image Editor的工具同样可以编辑资源文本但和本文的方法比较可得出下表
Image Editor BrccBMP 只支持位色任意色光标黑白两色任意色ICO只支持位色任意色AVI不支持支持WAV不支持支持
字体
字符串
其他
不支持支持
上面说的是直接在程序本身的调用其实资源文件还有其它用法比如说在你的程序携带其它文件要用的时候释放出来
例如: myexe exefile haexe//脚本文件
下面是自定义释放函数ExtractRes本例中使用如下:
ExtractRes(exefilemyexec:\newexe);
就把haexe以newexe为名字保存到C盘根目录下了
function TFormExtractRes(ResType ResName ResNewName: string): boolean;
var
Res: TResourceStream;
begin
try
Res := TResourceStreamCreate(Hinstance Resname Pchar(ResType));
try
ResSavetoFile(ResNewName);
Result := true;
finally
ResFree;
end;
except
Result := false;
end;
二中级应用篇
上面我们已经知道如何把一副BMP图像从资源文件里面读出来但是BMP文件太大了JPG文件应用的相对较多那么如何把JPG图像读出来呢?用资源文件加流方式即可具体方法如下:
()MyJpg JPEGMyJPG
()Var
Stream:TStream;
MyJpg:TJpegImage;
Begin
Stream=TResourceStreamCceat(HINSTANCEMyJpgJPEG);
Try
MyJpg:=TJpegImageCreate;
Try
MyJpgLoadfromStream(Stream);
ImagePictureAssignc(MyJpg);
Finally
MyJpgFree;
end;
Finally
StreamFree;
end;
end;
读取其它图片文件也是一样的比如说gif动画文件当然前提是你有一个gifpas这个单元很多站点都有的可以自己去找找实际应用中我还发现用上面的代码可以直接显示资源文件中的ICON和BMP
说到图形处理实际上还可以用Delphi创建调用纯图标资源的DLL比如说你可以看看超级解霸目录下的Dll很多就是纯图标资源而已具体方法如下:
():创建一个HiconRES文件这里不再重复
():新建一文本文件Icondpr内容如下:
library Icon;
{$R IconRES}
begin
end
用Delphi打开编译即可得到Icondll
():实际调用方法如下:
Private
Hinst:THANDLE;
VarHicon:THANDLE;
begin
Hinst:=Loadlibrary(Icondll);
IfHinst=ThenExit
Hicon:=Loadicon(HinstPchar(EditText));
IfHicon<>ThenImagePictureIconHandle:=Hicon;
FreeLibrary(Hinst);
end;
如果你的程序想在国际上供使用不同语言的人使用的话用Dll来存放字符资源将是一个好方法因为Dll不象ini文件那样可以被人随便修改特别是有时侯如果想保存一些版权信息的话用Dll就再好不过了比如说你准备开发一个汉字简繁体翻译器软件准备提供GbBig码和英文三种语言菜单给用户那么你可以试试用Dll来保存字符资源
我们需要建立三个Dll第一步当然是写Rc文件举Gb码为例内容如下:
/*MyScrc*/
#define IDS_MainForm_Caption
#define IDS_BtnOpen_Caption
#define IDS_BtnSave_Caption
#define IDS_BtnBig_Caption
#define IDS_BtnGb_Caption
#define IDS_BtnHelp_Caption
#define IDS_Help_Shelp
Stringtable
{
IDS_MainForm_Caption汉字简繁体翻译器
IDS_BtnOpen_Caption打开文件
IDS_BtnSave_Caption保存文件
IDS_BtnBig_Caption转换成Big
IDS_BtnGb_Caption转换成Gb
IDS_BtnHelp_Caption帮助
IDS_Help_Shelp输入文字或打开文件后按需要点击按钮即可转换!
}
第二步是Brcc编译为Res文件后用上面的方法得到Dll文件另外两个Dll用同样的方法生成下面来应用一下:
新建一个工程放上五个Button:BtnOpenBtnSaveBtnBigBtnGb和BtnHelp还有一个TComboBox:CbSelect用来选择语言种类的 具体代码如下:
unit Unit;
interface
private
SHelp: string;
function SearchLanguagePack: TStrings;
procedure SetActiveLanguage(LanguageName: string);
{ Private declarations }
implementation
procedure TFormCbSelectChange(Sender: TObject);
begin
SetActiveLanguage(CbSelectText);//调用相应Dll文件读取相应字符
end;
procedure TFormFormCreate(Sender: TObject);
begin
CbSelectItemsAddStrings(SearchLanguagePack);//搜索当前目录下所有的Dll文件名称
end;
function TFormSearchLanguagePack: TStrings;
var
ResultStrings: TStrings;
DosError: integer;
SearchRec: TsearchRec;
begin
ResultStrings := TStringListCreate;
DosError := FindFirst(ExtractFilePath(ParamStr()) + *dll faAnyFile SearchRec);
while DosError = do
begin
ResultStringsAdd(ChangeFileExt(SearchRecName ));
DosError := FindNext(SearchRec);
end;
FindClose(SearchRec);
Result := ResultStrings;
end;
procedure TFormSetActiveLanguage(LanguageName: string);
var
Hdll: Hmodule;
MyChar: array[] of char;
DllFileName: string;
begin
DllFileName := ExtractFilePath(ParamStr()) + LanguageName + dll;
if not FileExists(DllFileName) then Exit;
Hdll := loadlibrary(Pchar(DllFileName));
Loadstring(hdll MyChar );
SelfCaption := MyChar;
//读取字符资源表示资源文件中定义的
Loadstring(hdll MyChar );
SelfCaption := MyChar;
Loadstring(hdll MyChar );
BtnOpenCaption := MyChar;
Loadstring(hdll MyChar );
BtnSaveCaption := MyChar;
Loadstring(hdll MyChar );
BtnBigCaption := MyChar;
Loadstring(hdll MyChar );
BtnGbCaption := MyChar;
Loadstring(hdll MyChar );
BtnHelpCaption := MyChar;
Loadstring(hdll MyChar );
SHelp := MyChar;
Freelibrary(hdll);
ApplicationTitle := SelfCaption;
//
BtnOpenVisible := True;
BtnSaveVisible := True;
BtnBigVisible := True;
BtnGbVisible := True;
BtnHelpVisible := True;
//
end;
procedure TFormBtnHelpClick(Sender: TObject);
begin
ApplicationMessageBox(Pchar(SHelp) Http://lovejingtaocom MB_ICONINFORMATION);
end;
end
可能你会说这种方法还不如我自己在程序中直接定义三种具体的值来的方便甚至我自己自定义一个结构好了用不着用DLL那么麻烦的但是如果你的程序要用的字符很多呢?比如说Windows操作系统本身就有简体中文繁体中文英文等等版本用Dll的话只要直接替换DLL即可而不用每发行一个版本就打开代码来修改一次这样一来可以大大减少工作量和出错的机会说到这里再多说一句:Windows系统本身很多Dll带有了图片等资源我们可以在程序中直接调用这样一来我们的EXE也可以减少不少!当然最小的方法是实时生成技术老外曾经写了一个KB的程序就是利用了这个方法感兴趣的朋友可以到http://gocom/lovejingtao/haexe下载
三高级应用篇Delphi是个很有效率的开发工具但是它有一个缺点就是生成的EXE文件太大一个程序就算只有一个空窗口体积也有KB如果直接用API来写的话程序体积是小了但是又太繁琐无法立即看到界面效果根本谈不上是可视化开发其实并非鱼与熊掌不可兼得利用资源文件我们就可以轻松达到这个目的
在开始之前我们需要一个可以编辑资源文件的工具这类工具很多比如说Resource WorkShop就是非常好的一个如果一时找不到利用VC的编辑器来也是可以的下面我们就以VC的为例示范如何创建一个窗口资源文件运行VC打开菜单File>New将出现一个多项选择页我们选择Files>ResourceTemplate在右边的File填上DemoLocation选择保存路径然后点击按钮OK返回VC开发环境
选择菜单Insert>Resource将出现一个资源类型选择框我们把鼠标移到Dialog上面不用展开点击右边的New即可这时候返回VC开发环境并出现一个只有关闭按钮和两个Button的窗体将鼠标选定窗体击右键选择最后一项Properties将出现一个设置窗口将ID改为MAINFORM(注意:跟下面添加的其它控件的属性设置方法不同主窗口的ID必须把双引号写上去而且名称必须为大写否则程序将找不到资源程序会一运行就退出了)Caption改为安装程序这时候可以立刻看到窗口的标题变成了安装程序把Styles的Minimize box选上More Styles的Center勾上使程序运行时的位置居中当然你也可以设置它的坐标其它保留默认值即可回到开发环境在控件框里面分别选择一个Static Text一个Edit Box一个Button和一个Group Box添加到窗体上面把它们按照自己的爱好排列整齐然后逐个修改它们的属性方法就是按照上面说的选定控件后击右键选择最后一项Properties在出现的属性框里面修改其中属性如下:Group Box的Caption属性清空Static Text的Caption属性改为请选择安装目录:Edit Box的ID改为第一个Button的ID为Caption属性为选择第二个Button的ID为Caption属性为安装第三个Button的ID为Caption属性为退出为了使程序更加完美我们为它再添加一个菜单IDR_MENU选择Insert>Resource>Menu我们这里只简单添加一项文件>退出其中退出的ID为然后在主窗口的属性Menu设定为IDR_MENU即可
为了使程序更加美观我们再添加一个小图标同时这也将是我们程序的图标选择Insert>Resource>Icon>Import选择一个图标文件并将它的ID设置为MAINICON(注意:必须把双引号写上而且字母为大写)为窗口添加一个Picture控件并设置它的属性Type:IconImage下拉选择刚才的图标MainIcon即可
如果你想为程序在鼠标添加一些信息也是可以的选择Insert>Resource>Version即可
到这里我们已经完成了一个简单的安装程序的窗体设计实际上我们现在就可以在Delphi中调用它了我们先把劳动成果保存起来选择File>Save As在文件类型里选择bit Resource File(res)保存为Demores文件大小大约为KB
新建一个扩展名为dpr的文本文件MyDemoDpr键入如下代码:
Uses WindowsMessages;
{$R DemoRes}
function MainDialogProc(DlgWin:hWnd;DlgMessage:UINT;DlgWParam:WPARAM;DlgLParam:LPARAM):integer;stdcall;
begin
Result := ;
case DlgMessage of
WM_Close:
begin
PostQuitMessage();
Exit;
end;
end;
end;
begin
DialogBox(hInstance MAINFORM @MainDialogProc);
end
用Delphi打开它编译一次即可产生一个大小为KB的EXE是不是很小!实际上你甚至只用一行代码就把它Show出来不过程序无法关闭而已
Uses Windows;
{$R DemoRes}
function MainDialogProc: integer;
begin
Result := ;
end;
begin
DialogBox(hInstance MAINFORM @MainDialogProc);
end
上面的程序只不过是一个空窗口而已现在我们来写代码响应按下相应按钮响应的事件完整代码如下:
program MyDemo;
uses Windows Messages shlobj;
const
ID_Edit = ;
ID_Selet = ;
ID_Setup = ;
ID_Quit = ;
ID_Exit = ;
{$R DemoRes}
var
MainWin: HWND;
function My_Gettext: string;
var
Textlength: Integer;
Text: PChar;
s: string;
begin
TextLength := GetWindowTextLength(GetDlgItem(MainWin ID_Edit));
GetMem(Text TextLength + );
GetWindowText(GetDlgItem(MainWin ID_Edit) Text TextLength + );
s := text;
FreeMem(Text TextLength + );
Result := s;
end;
function Getmyname: string;
var
i j: integer;
begin
J := ;
for i := to length(ParamStr()) do
if ParamStr()[i] = \ then J := I;
Result := copy(ParamStr() J + length(ParamStr()) J);
end;
function SelectDirectory(handle: hwnd; const Caption: string; const Root:WideString;outDirectory:string): Boolean;
var
lpbi: _browseinfo;
buf: array[MAX_PATH] of char;
id: ishellfolder;
eaten att: cardinal;
rt: pitemidlist;
initdir: pwidechar;
begin
result := false;
lpbihwndOwner := handle;
lpbilpfn := nil;
lpbilpszTitle := pchar(caption);
lpbiulFlags := BIF_RETURNONLYFSDIRS + BIF_EDITBOX;
SHGetDesktopFolder(id);
initdir := pwchar(root);
idParseDisplayName( nil initdir eaten rt att);
lpbipidlRoot := rt;
getmem(lpbipszDisplayName MAX_PATH);
try
result := shgetpathfromidlist(shbrowseforfolder(lpbi) buf);
except
freemem(lpbipszDisplayName);
end;
if result then
begin
directory := buf;
if length(directory) <> then directory := directory + \;
end;
end;
function MainDialogProc(
DlgWin: hWnd;
DlgMessage: UINT;
DlgWParam: WPARAM;
DlgLParam: LPARAM
)
: integer; stdcall;
var
MyIcon: HICON;
Sdir: string;
begin
Result := ;
case DlgMessage of
WM_INITDIALOG:
begin
MyIcon := LoadIcon(hInstance MainIcon);
SetClassLONG(DlgWin GCL_HICON MyIcon);
MainWin := DlgWin;
end;
WM_Close:
begin
PostQuitMessage();
Exit;
end;
WM_COMMAND:
case LOWORD(DlgWParam) of
ID_Selet:
begin
if SelectDirectory(DlgWin 请选择安装目录 Sdir)
then SendMessage(GetDlgItem(DlgWin ID_Edit) WM_SETTEXT lParam(pChar(Sdir)));
end;
ID_Setup:
begin
if My_Gettext = then
begin
MessageBox(DlgWin 请先选择安装文件夹! 信息 MB_ICONINFORMATION + MB_OK);
Exit;
end;
CopyFile(pchar(ParamStr()) pchar(My_Gettext + Getmyname) false);
MessageBox(DlgWin 安装完毕! 信息 MB_ICONINFORMATION + MB_OK);
PostQuitMessage();
Exit;
end;
ID_Quit:
begin
PostQuitMessage();
EXIT;
end;
ID_Exit:
begin
if MessageBox(DlgWin 你点击了菜单退出你确定退出程序吗? 信息 MB_ICONQUESTION + MB_OKCANCEL) = IDOK then
PostQuitMessage();
Exit;
end;
end;
end;
end;
begin
DialogBox(hInstance MAINFORM @MainDialogProc);
end