三、實際應用之二:利用串流製作可執行電子賀卡
我們常看到一些電子賀卡之類的製作軟體,可以讓你自己選擇圖片,然後
它會產生一個EXE可執行檔給你。打開賀卡時就會一邊放音樂一邊顯示出圖片來。
現在學了流操作之後,我們也可以做一個了。
加圖過程我們可以直接用前面的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 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.
怎麼樣?很神奇吧:)把程式介面弄的漂亮點,再增加一些功能,你會發現比
起那些要註冊的軟體來也不會遜多少吧。