那位大侠指条路子给在下,不胜感激!
解决方案 »
- quickreport报表分组统计中的expression用到数据模块中的数据,就不能正常显示,请问该怎么办?
- 兩字符串比較﹐獲取不同部分
- 问问FastReport如何动态分类
- 如何实现winamp吸附当前窗口标题栏的效果?解决后另有重谢!!!
- 求救:两台机器用Modem连接后,一台机器怎么访问另一台机器?
- 兄弟们,朋友们,有没有多线程dll的例子? 谢谢
- 求助高手:SQL到Access的转换
- 过客!过客!过客!过客!过客!过客!, 我已装了Appcontrols Suite 2.6 (TAppBar ),请问怎样做类似于QQ 那个的窗体呢?
- 如何遍历组件(非数组形式)
- 求救!!!!关于MIDAS的问题
- dephi包问题!!!急!!!送50分!!!!
- 为什么两次执行Edit1 和 Edit2 的内容不一样啊???
一.什么是资源(Resource)
广义的资源,是指在编程当中可以使用的任何的图片、文字、声音、文件等等。狭义的资源,是指经过特殊方法编译的包含在可执行文件(EXE、DLL等等)中的供程序使用的图片、声音、文字和文件等等。我们在这里所说的资源指狭义的资源。资源的使用,就好象烧菜,作一道菜要求色香味俱全,做程序也是这样,利用这个资源可以使程序色香味俱全。不管那本书,还有互联网络上面,关于资源的文章都是非常少的,下面是作者使用资源的一些心得和技巧,而且关于资源的论述和说明都是比较详细和齐全的。二.资源脚本
在Delphi中,要使用资源(在VC中也一样),需要先编写一个资源文件脚本,不是能够拿来就用的,就和吃饭一样,都先要煮一次一样。资源脚本编写好之后,然后用资源编译器进行编译,得到一个临时的资源文件(.RES),最后,程序编译的时候,包含这个RES文件,这样就可以在程序中使用资源了。1) 资源类型
资源类型分为两种:预定义和用户自定义类型A) 常见的预定义资源类型BITMAP
位图资源
LANGUAGE
定义语言资源
CURSOR
光标资源
MENU
菜单资源
STRINGTABLE
字符串资源表
DIALOG
对话框资源
VERSION
版本资源
FONT
字体资源
ACCELERATORS
快捷键资源
MESSAGETABLE
消息表资源
其中红色的是大家应该掌握的,蓝色的大家也要用到,但是可以使用Delphi提供的手段来完成,不需要大家用资源脚本来编写。版本资源将在后面的内容中单独讲解。其它的不需要大家掌握,这些在VC中使用的比较多,因为Delphi有自己的处理方式,没有必要用到他们,否则就丧失了Delphi进行RAD开发的优势。B) 用户自定义格式资源有一个预定义的表明是用户自定义资源的关键字:RCDATA。除了系统预定义的这些关键字之外,凡是其它的名字如EXEFile,AVIFile,Test等等,都视为用户自定义资源类型。一般用户自定义资源是有的程序需要带一些附加资源,或者需要包含其它的文件,但是作者在发布程序的时候出于某些原因,不希望很多文件或者保密等等,就把这些附加的文件包含到EXE里面,那么EXE运行的时候,再临时释放出来,使用之后又删除。2) 常用资源脚本命令格式
说明:i) BEGIN,END:用于表示资源块的开始、结束,字符串用双引号括起来;D) 资源定义的顺序没有关系;E) 命令大小写无所谓,注释采用//格式,每一个资源定义中间不要用其它分隔符;F) 每一个资源都有一个名字或者整数标志用于区分资源。因为整数标记比较难于记忆,容易混淆,随意可以采取常量定义帮助记忆,常量定义采用#Define格式,例如#Define ID_FORMCAPTION 100;G) 可以包含其它文件,用#include包含即可,例如:#include “consts.pas”,这个功能主要用来配合Delphi来使用常量定义。C) 定义位图资源格式:ResourceName BITMAP “BitmapFileName.BMP”这个命令用于把BitmapFileName指定的位图文件,变成一个名字为ResourceName的资源。BitmapFileName可以带路径,也可以不带,不带路径的话,则默认为当前目录下的文件。BitmapFileName这个文件必须存在,否则编译资源的时候出错。D) 定义光标资源CursorResourceName CURSOR “CursorFileName.CUR”说明同Bitmap。E) 定义图标资源IconResourceName ICON “IconFileName.ICO”同上。F) 定义字符串资源字符串的定义如下:STRINGTABLEBEGIN ID_CAPTION,’这是一个常量定义的字符串,很好记忆的’ 102,’这是一个整数定义的字符串,看看你记不记得住?’ …ENDG) 用户自定义资源这是一个很重要的,其实也和前面差不多。MyFileRes DemoTest “FileName”用户自定义资源很不同的操作之处在于后面Load资源的代码上面。
为了让大家熟悉资源脚本的编写,下面给出一个比较全面的资源脚本范例,在实际的编程当中,大家可以根据需要删除或者修改、添加一些内容就可以了,这个文件可以作为资源脚本文件的模板。///下面的文件内容是脚本文件和Delphi共享的文件内容///FileName:MyConsts.Pas///*******Cut From Here*********///unit images; interface const IDB_WARNNING = 1; IDS_MESSAGE=2; ///…implementation end.///*******Cut End Here*****************///从下面开始是资源脚本文件内容///FileName:Demo.RC///*******Demo.RC:Cut From Here ******///#include "MyConsts.Pas"#define ID_OK 100#define ID_CANCEL 101#define ID_PROMPT 200#define ID_LABEL 500#define ID_GROUPBOX 501#define IDC_RADIO1 502#define IDC_RADIO2 503#define IDC_EDIT1 504#define ID_FILE_OPEN 310#define ID_FILE_EXIT 311#define ID_EDIT_COPY 320#define ID_EDIT_CUT 321#define ID_EDIT_LINK 322 ///----Define Bitmap Resource--------//////下面用字符串来区分资源Photo BITMAP "C:\Windows\Wallpaper.BMP" ///文件名可不用"",但建议使用""///下面用整数来区分资源,其它类型资源定义类似IDB_WARNNING BITMAP "Warning.BMP" ///----Define ICON Resource--------////Girl ICON "Girl.ICO" ///----Define Cursor Resource------////HandPoint CURSOR Hand.CUR ///----User Define Resource-------////MyResource MyFile "MyFileName.Ext" ///----Define String Resource-----////STRINGTABLEBEGIN ID_OK,"确定" ID_CANCEL,"取消" ID_PROMPT,"Delphi课程演示程序" 102,"这是一个直接用数值定义的字符串"END ///----Define MainMenu Resource----///////定义的菜单如下图////┏━━━━━━━━━━━━━┓////┃File Edit ┃////┣━━━━┳━━┳━━━━━┫////┃Open ┃ ┃Copy ┃////┣━━━━┫ ┃Cut ┃////┃Exit ┃ ┣━━━━━┫////┗━━━━┛ ┃Link ┃//// ┗━━━━━┛DemoMenu MENU DISCARDABLEBEGIN POPUP "&File" BEGIN MENUITEM "&Open...", ID_FILE_OPEN MENUITEM SEPARATOR MENUITEM "E&xit", ID_FILE_EXIT END POPUP "&Edit" BEGIN MENUITEM "&Copy", ID_EDIT_COPY MENUITEM "C&ut", ID_EDIT_CUT MENUITEM SEPARATOR MENUITEM "HyperLink...", ID_EDIT_LINK ENDEND ///----Define A Dialog-------////IDD_DIALOG1 DIALOG DISCARDABLE 0, 0, 187, 98STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENUCAPTION "对话框"FONT 10, "宋体"BEGIN DEFPUSHBUTTON "确定",IDOK,130,7,50,14 PUSHBUTTON "取消",IDCANCEL,130,24,50,14 LTEXT "Test Label",ID_LABEL,21,13,35,8 GROUPBOX " Group Box: ",ID_GROUPBOX,14,28,90,40 CONTROL "Radio1",IDC_RADIO1,"Button",BS_AUTORADIOBUTTON,21,37,39, 10 CONTROL "Radio2",IDC_RADIO2,"Button",BS_AUTORADIOBUTTON,21,53,39, 10 EDITTEXT IDC_EDIT1,14,71,89,12,ES_AUTOHSCROLLEND ///*******Demo.RC:Cut End Here******/// 资源脚本的编写很麻烦,有没有简单的方法来编写呢?有!利用VC++即可。Borland的Brcc32.Exe可以编译VC写出来的RC文件!不过在编译VC写的RC文件之前,必须修改RC文件,把其中的Include “afxres.h”删除即可。则真的是一件很奇怪的事情,Brcc32可以编译VC写的资源脚本,而VC的资源脚本采用的却是BEGIN..END,而不是{},好象有Pascal的味道哦。:)三.资源的编译
如果用户使用自己的资源的话,Delphi不会自动编译资源,需要手动编译。在Delphi中能够自动编译的资源是窗体,大家打开一个窗体的pas文件就可以看到{$R *.DFM}这样的语句,这就是窗体资源。如果要编译资源,请采用下面的命令即可:Brcc32 ResourceScriptFileName上面是一个DOS命令,可以命令提示符下面运行,其中Brcc32就是编译资源的命令;ResourceScriptFileName是资源脚本文件的名字。运行之后,如果没有错误,那么会生成一个同名的.Res文件。Brcc32命令有很多的附加参数,请使用Brcc32 /?获取详细的说明。资源脚本经过编译之后,可以不依赖原来的文件,单独使用。注意,如果你的程序没有修改,而修改了资源的话,需要用Build All来强制编译所有的程序文件,这样才能保证你的程序是正确的。否则,根据Delphi的增量编译原则,没有修改的程序文件是不会编译的!四.资源的使用
编译指令:{$R FileName.RES}
{$R FileName.RES}这个编译指令用于指示编译器在编译生成EXE或者DLL的时候,把指定的资源文件也包括进来。这个编译指令应该包含在implementation部分,写在{$R *.DFM}附近。如果你的程序中使用了某个资源,而又没有使用$R指令包含到EXE(DLL)中的话,你的程序将不能正常运行。
ResourceString是一个关键字,用于定义资源字符串常量。我们知道普通的字符串常量用const就可以定义,但是const定义的字符串是内嵌在程序代码中间的,不是资源,而ResourceString定义的字符串使用的时候和const定义的是一样的,但是是作为资源保存在EXE(DLL)中间的,并且ResourceString也避免了写资源脚本和编译资源的麻烦。装载资源
需要注意的是,在使用某些API函数Load资源的时候,一般都需要一个ResourceName或者ResourceID,而这些函数的参数类型都是Pchar,因此,如果使用ResourceID的话,直接使用100这样的数是不行的,必须用MAKEINTRESOURCE(100)来代替。具体的例子,请看下面的LoadCursor!位图资源的装载如下:VarBmp:TBitmap;BeginBmp:=TBitmap.Create;Bmp.LoadFromResourceName(hInstance,’ResourceName’);///或者是 Bmp.LoadFromResourceID(hInstance,ResourceID);…Bmp.Free;End;字符串资源的装载如下:ResultString:=LoadStr(StringID);遗憾的是,Cursor资源没有LoadFromResource的功能,因此,Load一个光标资源比较麻烦!需要借助于一个临时文件或者利用API函数。LoadCursorFromFile(‘CursorFileName’);LoadCursor(hInstance,’ResNameOrResID’);///例:LoadCursor(hInstance, MAKEINTRESOURCE(100));///例:LoadCursor(hInstance, ‘Hand’);装载Cursor代码如下:Screen.Cursors[curIndex]:=LoadCursor(hInstance,’Hand’);Control.Cursor:=curIndex;一般的做法是定义一个常量,例如const MyCursor=20;然后用类似的代码即可:Screen.Cursors[MyCursor]:=LoadCursor(hInstance,’hand’);Memo1.Cursor:=MyCursor;当然,你也可以使用预定义的常量如crHandPoint等等。如果要是整个程序的光标都改变的话,只要用如下的代码即可:Screen.Cursor:=MyCursor; 图标资源的装载和Cursor类似,有一个LoadIcon()API可以装载Icon!例如: LoadIcon(hInstance,’AppIcon’); 自定义资源的装载,比较麻烦,不过幸好Delphi提供了一个类TResourceStream,这样可以比较方便和轻松地装载资源了。装载自定义资源的时候,需要一个资源类型,这是一个Pchar类型的参数,请传入和RC中一样的名字即可。利用TResourceStream可以做到很多的工作。下面的代码是把在Exe里面的一个类型为ExeFile的自定义资源提取出来,保存称为一个临时文件。procedure TMainForm.GenUpxExeFile;var UpxExeStream : TResourceStream;begin UpxExeStream := TResourceStream.Create(HInstance, 'ExeFile', 'EXEFILE'); UpxExeStream.SaveToFile(UpxExeFileName); UpxExeStream.Free;end;Delphi应用程序文字信息的汉化
我们知道,当Delphi写的应用程序使用ShowMessage或其它类似的函数的时候,显示的对话框中按钮的文字或信息是英文的,这出现在一个中文程序中就很别扭,那么有没有可能把Delphi中的这些错误信息变成中文的呢?答案是:当然可以。有两种方法可以做到这一点:第一种,采用修改EXE的方法。当程序编译完成之后,会生成一个EXE,其中就包含了那些英文信息,此时,可以采用资源编辑工具如ExeScope,VC等等对这个EXE进行编辑,修改其中的英文为中文即可。这种方法有几个很大的缺点,首先是你每编译一次,那么你要分发程序给客户使用的话,就必须修改EXE一次,这样重复劳动,费力不讨好;其次,如果你写了多个不同的程序,那么每个程序的EXE你都要修改一次,很麻烦;还有,因为编译之后,字符串的长度就固定了,因此,你在修改EXE的时候,需要注意翻译过来的文字的长度不能超过原来的,这样就有很大的限制。第二种,采用修改Delphi的Source Pas文件的方法。这个方法是最好的,克服了前面的那种做法的缺点。推荐使用修改PAS文件的方法。我们知道,Delphi发布的时候,已经把VCL的源代码文件也一起发布了,在$(Delphi)\Source目录下面就是Delphi的源代码文件,特别是VCL子目录,就是Delphi这个VCL核心的源代码
int 文件名长度
char 文件名[文件名长度]
int 文件数据长度
char 文件数据[文件数据长度]
范例程序:
function CreatePackage(FileList:TStringList;PackageName:string):boolean;stdcall;
var
I: Integer;
PackWriter,FileReader: TFileStream;
str_filename:string;
p_filename:PChar;
i_fmLength,i_fSize:integer;
buffer:PChar;
begin
PackWriter := TFileStream.Create(PackageName,fmCreate); for I := 0 to FileList.Count - 1 do // Iterate
begin
FileReader := TFileStream.Create(FileList[I],fmOpenRead and (fmShareDenyNone));
//获取各种信息
str_filename := ExtractFileName(FileList[I]);
p_filename := PChar(str_filename);
i_fmLength := Length(str_filename);
i_fSize := FileReader.Size;
try
try
PackWriter.Write(i_fmLength,SizeOf(i_fmLength));
PackWriter.Write(p_filename^,i_fmLength);
PackWriter.Write(i_fSize,SizeOf(i_fSize));
GetMem(buffer,i_fSize);
FileReader.ReadBuffer(buffer^,i_fSize);
PackWriter.Write(buffer^,i_fSize);
except on e: Exception do
result := false;
end
finally
FileReader.Free;
end; //try
end; // for
PackWriter.Free;
result := true;
end;解包程序:function ExtractFile(PackageName:string;FileName:string;DesFileName:string):boolean;stdcall;
var
FileNeedExtract: TMemoryStream;
FP:TFileStream;
buffer:PChar;
FileData:PChar;
i_FmLength:integer;
i_FLength:integer;
begin
FP := TFileStream.Create(PackageName,fmOpenRead and (fmShareDenyNone));
try
try
while FP.Position <> FP.Size do
begin
FP.Read(i_FmLength,SizeOf(i_FmLength));
GetMem(buffer,i_FmLength);
FP.Read(buffer^,i_FmLength);
FP.Read(i_FLength,SizeOf(i_FLength));
if buffer = FileName then
begin
GetMem(FileData,i_FLength);
FP.Read(FileData^,i_FLength);
FileNeedExtract := TMemoryStream.Create;
FileNeedExtract.Size := 0;
FileNeedExtract.Position := 0;
FileNeedExtract.Write(FileData^,i_FLength);
FileNeedExtract.SaveToFile(DesFileName);
FileNeedExtract.Free;
end
else
FP.Position := FP.Position + i_FLength;
end;//while
except on e:Exception do
result := false;
end;
finally
FP.Free;
end;
result := true;
end;
Delphi 中关于流我还有一个问题,为什么在写入的时候只能使用指针呢?
为什么不能直接写入字符串?
Delphi 中关于流我还有一个问题,为什么在写入的时候只能使用指针呢?
为什么不能直接写入字符串?
资源文件最大的好处是能将一些在必要时才调用的文件跟可执行文件一起编译,生成一个文件.这样做最大的好处就是使外部文件免遭破坏.例如在一条程序中你要临时调用一幅图片,一般作法是把图片放在某一路径下(通常是主程序所在路径),但如果用户路径误删你的图片文件,则可能使程序找不到相应文件而出错崩溃。另外,如果你想自己的程序界面美观,想用一些自定义光标,也要用到资源文件。
资源文件的使用步骤为:
1.编写rc脚本文本
用记事本或其它文本编辑器编写一个扩展名为rc的文件。例如:mycur cursor move.cur //加入光标
mypic Bitmap Water.BMP //加入位图
mywav WAVE happy.wav //加入声音
myAVI AVI EPOEN.AVI //加入视频
myIco ICON CJT.ICO //加入图标 格式分别为在资源文件中的名称->类型->实际文件名称,例如上面第一行 定义一个名为mycur的光标,实际名称为加入光标move.cur.
2.将rc文件编译成res资源文件
将脚本文件和实际文件拷到Brcc32.EXE所在目录,执行DOS命令。格式为:Brcc32 脚本文件(回车),例如有一名为myfirst.rc的脚本文件,则执行 Brcc32 myfirst.rc(回车)即可。如果你是懒人,也可新建一批处理文件,内容 只有一行:Brcc32 mufist.rc.(因为Delphi安装后一般会在自动批处理文件中指明搜索路径的。)如果编译成功,则会生成一个结尾为res的文件,这个 文件就是我们需要的资源文件。
3.在Delphi单元中加入资源文件
将生成的res资源文件拷贝到你所编程序的路径下,在单元文件{$R *DFM}后加上一句{$R mufirst.res},则将res文件加入去,编译后资 源文件即已包含在可执行文件中了。若你有多个资源文件,也按上法依次加入。
4.在Delphi程序中调用资源文件
资源文件在Delphi中的关键字为hinstance.下面给出具体用法
光标的调用
首先在程序中定义一个值大于0的常量,因为Delphi本身用0-负16来索引 默认的光标,所以我们制定的光标应从表面上1开始索引。然后在窗口的Oncreat事件中添加以下代码:
screen.cursor[35]:=Loadcursor (hinstance,'mycur');
其中35为大于1的常量,mycur为光标在资源文件中的名字。如果希望在 其他控件上使用定制光标,例如Panel控件,只需在程序的适当处加入以下代码:
Panel1.cursor:=35;
位图的调用
新建一项工程,添加一Timage控件,在需要显示的地方写以下代码:
Var mymap:Hbitmap;
begin
mymap:=LoadBitmap(hinstance,'mypic');
Image1.picture.Bitmap.Handle:=mymap;
end;
其中"mypic"为位图资源文件中的名称。
〈3〉AVI文件的调用
新建一工程,添加一Animate控件,在需要的地方加入:
animater1.resname:='myAVI';
animater1.Active:=true;
其中myAVI为视频文件在资源文件中的名称。
〈4〉调用WAV文件
在uses中加入mmsystm单元,以便在程序中播放WAV文件。播放时Playsound(pchar('mywav'),hinstance,sndsync or snd_resource);其中mywav为声音文件在资源中的名称。
〈5〉加入光标
加入光标比较容易,只要将res文件加入单元文件中即可。但需注意,名称最好取"W"."WW"等,使第一个字母尽量靠后,以免与主程序的图标顺序颠倒。这样一来,别人在使用你的程序时如果想选择其它图标就有很多选择了。
补充:
1.资源类型除上述类型外,还可以字体文件,字符串文件等。
2.资源文件不但可以在标准图形界面下使用还可在控制台下使用。
下面我们来试验一下:
新建一工程,将唯一的一个Form删除,然后修改工程文件。增加一句{$Apptype console},在uses子句中加入mmsystem,并将其它引用单元删掉。将Begin和end之间语句删掉。至此,我们就可和Turbo PASCAL下编程序一样,且还可以调用windows的API和资源。将资源文件----{$R myfist.res}加入。在Begin和end之间写下:
writeln('演示程序,按任意键开始!');
readln;
playsound(pchar('mywav'),hinstance,snd_sync or snd_resource);
writeln('演示结束!');
运行程序,将弹出一个标准DOS窗口,按任意键播放声音文件。是不是很COOL呢!我曾下载过一个播放器,在其安装目录下我发现有一"DOS程序",用鼠标双击它便弹出一个DOS窗口,显示DOS时代特有的画图,并有背景音乐!可能就是用这个方法做的。
3.Delphi本身自带了一个叫Image Editor的工具,同样可以编辑资源文本,但和本文的方法比较,可得出下表:**************************************
Image Editor Brcc32BMP 只支持16位色 任意色光标 黑白两色 任意色ICO 只支持16位色 任意色AVI 不支持 支持WAV 不支持 支持字体
字符串 不支持 支持
其他
****************************************
例如: myexe exefile 'ha1.exe'//脚本文件
下面是自定义释放函数ExtractRes,本例中使用如下:ExtractRes('exefile','myexe','c:\new.exe');就把ha1.exe以new.exe为名字保存到C盘根目录下了. function TForm1.ExtractRes(ResType, ResName, ResNewName: string): boolean;
var
Res: TResourceStream;
begin
try
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
try
Res.SavetoFile(ResNewName);
Result := true;
finally
Res.Free;
end;
except
Result := false;
end; 利用资源文件,还可以作出其它有用且有趣的效果。比如说结合VC来编辑资源文件,将程序的窗口先画出来,然后直接调用,就可以做出又美观体积又小的DELPHI程序了.
用记事本或其它文本编辑器编写一个扩展名为rc的文件。例如:mycur cursor move.cur //加入光标
mypic Bitmap Water.BMP //加入位图
mywav WAVE happy.wav //加入声音
myAVI AVI EPOEN.AVI //加入视频
myIco ICON CJT.ICO //加入图标 格式分别为在资源文件中的名称->类型->实际文件名称,例如上面第一行 定义一个名为mycur的光标,实际名称为加入光标move.cur.
2.将rc文件编译成res资源文件
将脚本文件和实际文件拷到Brcc32.EXE所在目录,执行DOS命令。格式为:Brcc32 脚本文件(回车),例如有一名为myfirst.rc的脚本文件,则执行 Brcc32 myfirst.rc(回车)即可。如果你是懒人,也可新建一批处理文件,内容 只有一行:Brcc32 mufist.rc.(因为Delphi安装后一般会在自动批处理文件中指明搜索路径的。)如果编译成功,则会生成一个结尾为res的文件,这个 文件就是我们需要的资源文件。
算了,自己看好了,delphi应该有详细帮助的,这两天熬夜,过段时间再看这个问题。
能把单个的一个文件当作简单的文件系统来用,可以设卷标,
里面可以建目录、子目录、存放,删除文件...
还提供PopulateTreeView(TreeView : TTreeView)这样的函数,直接用TreeView
显示内容...
另外,还可以用微软的结构化存储
http://hubdog.csdn.net/Hubdog/olestore.htm
添加图片过程我们可以直接用前面的Cjt_AddtoFile,而现在要做的是如何把图像读出并显示。我们用前面的Cjt_LoadFromFile先把图片读出来保存为文件再调入也是可以的,但是还有更简单的方法,就是直接把文件流读出来显示,有了流这个利器,一切都变的简单了。
现在的图片比较流行的是BMP格式和JPG格式。我们现在就针对这两种图片写出读取并显示函数。 Function Cjt_BmpLoad(ImgBmp:TImage;SourceFile:String):Boolean;
var
Source:TFileStream;
MyFileSize:integer;
begin
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);
try
try
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));//读出资源
Source.Seek(-MyFileSize,soFromEnd);//定位到资源开始位置
ImgBmp.Picture.Bitmap.LoadFromStream(Source);
finally
Source.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
上面是读出BMP图片的,下面的是读出JPG图片的函数,因为要用到JPG单元,所以要在程序中添加一句:uses jpeg。 Function Cjt_JpgLoad(JpgImg:Timage;SourceFile:String):Boolean;
var
Source:TFileStream;
MyFileSize:integer;
Myjpg: TJpegImage;
begin
try
Myjpg:= TJpegImage.Create;
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareDenyNone);
try
Source.Seek(-sizeof(MyFileSize),soFromEnd);
Source.ReadBuffer(MyFileSize,sizeof(MyFileSize));
Source.Seek(-MyFileSize,soFromEnd);
Myjpg.LoadFromStream(Source);
JpgImg.Picture.Bitmap.Assign(Myjpg);
finally
Source.Free;
Myjpg.free;
end;
except
Result:=false;
Exit;
end;
Result:=true;
end;
有了这两个函数,我们就可以制作读出程序了。下面我们以BMP图片为例:
运行Delphi,新建一个工程,放上一个显示图像控件Image1。在窗口的Create事件中写上一句就可以了:
Cjt_BmpLoad(Image1,Application.ExeName);
这个就是头文件了,然后我们用前面的方法生成一个head.res资源文件。
下面就可以开始制作我们的添加程序了。全部代码如下:
unit Unit1; interface uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ExtCtrls, StdCtrls, ExtDlgs; type
TForm1 = class(TForm)
Edit1: TEdit;
Button1: TButton;
Button2: TButton;
OpenPictureDialog1: TOpenPictureDialog;
procedure FormCreate(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
private
Function ExtractRes(ResType, ResName, ResNewName : String):boolean;
Function Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
{ Private declarations }
public
{ Public declarations }
end; var
Form1: TForm1; implementation {$R *.DFM}
Function TForm1.ExtractRes(ResType, ResName, ResNewName : String):boolean;
var
Res : TResourceStream;
begin
try
Res := TResourceStream.Create(Hinstance, Resname, Pchar(ResType));
try
Res.SavetoFile(ResNewName);
Result:=true;
finally
Res.Free;
end;
except
Result:=false;
end;
end;
Function TForm1.Cjt_AddtoFile(SourceFile,TargetFile:string):Boolean;
var
Target,Source:TFileStream;
MyFileSize:integer;
begin
try
Source:=TFileStream.Create(SourceFile,fmOpenRead or fmShareExclusive);
Target:=TFileStream.Create(TargetFile,fmOpenWrite or fmShareExclusive);
try
Target.Seek(0,soFromEnd);//往尾部添加资源
Target.CopyFrom(Source,0);
MyFileSize:=Source.Size+Sizeof(MyFileSize);//计算资源大小,并写入辅程尾部
Target.WriteBuffer(MyFileSize,sizeof(MyFileSize));
finally
Target.Free;
Source.Free;
end;
except
Result:=False;
Exit;
end;
Result:=True;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Caption:='Bmp2Exe演示程序.作者:陈经韬';
Edit1.Text:='';
OpenPictureDialog1.DefaultExt := GraphicExtension(TBitmap);
OpenPictureDialog1.Filter := GraphicFilter(TBitmap); Button1.Caption:='选择BMP图片';
Button2.Caption:='生成EXE';
end; procedure TForm1.Button1Click(Sender: TObject);
begin
if OpenPictureDialog1.Execute then
Edit1.Text:=OpenPictureDialog1.FileName;
end; procedure TForm1.Button2Click(Sender: TObject);
var
HeadTemp:String;
begin
if Not FileExists(Edit1.Text) then
begin
Application.MessageBox('BMP图片文件不存在,请重新选择!','信息',MB_ICONINFORMATION+MB_OK)
Exit;
end;
HeadTemp:=ChangeFileExt(Edit1.Text,'.exe');
if ExtractRes('exefile','head',HeadTemp) then
if Cjt_AddtoFile(Edit1.Text,HeadTemp) then
Application.MessageBox('EXE文件生成成功!','信息',MB_ICONINFORMATION+MB_OK)
else
begin
if FileExists(HeadTemp) then DeleteFile(HeadTemp);
Application.MessageBox('EXE文件生成失败!','信息',MB_ICONINFORMATION+MB_OK)
end;
end;
end.
怎么样?很神奇吧:)把程序界面弄的漂亮点,再添加一些功能,你会发现比起那些要注册的软件来也不会逊多少吧。
(以上转载)