This article attempts to explain how to include files inside a Delphi unit /
application as different kinds of binaries and how to manage them without the
resource technology.
The app is called the Hexer.
Put your files into your delphi project at design time and then just compile it to
get all into one or more units.
First you have to convert the file in a delphi unit by the Hexer. Then you call it
from your own app which embedds the unit.
You can even store waves or pictures and play it without the need to create a file,
play it from memory.
1
2 if not PlaySound(@UtopiaWinstarten_wav, 0, SND_MEMORY + SND_SYNC)
3
4 {It is possible to embed any kind of file (also executables) in an executable using
5 the Hexer. First example is a picture: }
6
7 procedure TForm1.btnPicloadClick(Sender: TObject);
8 var mybitmap: TBitmap;
9 bitStream: TStream;
10 begin
11 //mybitmap.LoadFromFile('dws_logo.bmp'); for the mortals
12 mybitmap:= TBitmap.Create;
13 bitStream:= TMemoryStream.Create;
14 try
15 bitStream.Writebuffer(dws_logo_bmp, sizeof(dws_logo_bmp));
16 bitStream.Position:= 0;
17 mybitmap.LoadFromStream(bitStream);
18 if assigned(mybitmap) then begin
19 image1.Picture.assign(mybitmap);
20 image1.update;
21 end;
22 finally
23 bitStream.Free;
24 mybitmap.Free;
25 end;
26 end;
27
28 //Second example is an executable:
29
30 procedure TForm1.btnApploadClick(Sender: TObject);
31 var mybitmap: TBitmap;
32 bitStream: TMemoryStream;
33 begin
34 mybitmap:= TBitmap.Create;
35 bitStream:= TMemoryStream.Create;
36 try
37 bitStream.Writebuffer(viergewinnt_exe, sizeof(viergewinnt_exe));
38 bitStream.Position:= 0;
39 bitstream.LoadFromStream(bitstream);
40 bitstream.SaveToFile('vierg.exe');
41 WinExec(pchar('vierg.exe'){ + ' ' + ParamStr},SW_NORMAL);
42 finally
43 bitStream.Free;
44 mybitmap.Free;
45 end;
46 end;
47
48 //Third example is a zip file or like ASPack works too:
49
50 //hexer2_zip is the name of the bytearray in the unit
51 bitStream:= TMemoryStream.Create;
52 try
53 bitStream.Writebuffer(hexer2_zip, sizeof(hexer2_zip));
54 bitStream.Position:= 0;
55 bitstream.LoadFromStream(bitstream);
56 bitstream.SaveToFile('vierg2.zip');
57 case shellapi.shellExecute(0,'open', pchar('vierg2.zip'),'',nil,
58 SW_SHOWNORMAL) of
59 0: showmessage('out of memory or resources');
60 ERROR_BAD_FORMAT: showmessage('file is invalid in');
61 ERROR_FILE_NOT_FOUND: showmessage('file was not found');
62 ERROR_PATH_NOT_FOUND: showmessage('path was not found');
63 end;
64 finally
65 bitStream.Free;
66 end;
67
68 --------------------------------------------------------------------
69 {How does the Hexer works?
70 the Hexer is generally an executable which converts the file into a unit. You
71 choose the name of the file to be converted and the name of the resulting unit.}
72
73 MainForm2.TForm1.btnConvertClick (97i)
74 MainForm2.TForm1.ConvertToUnit (103i)
75 MainForm2.WriteString (108i)
76 MainForm2.EmbedFile (117i)
77 MainForm2.WriteString (108i)
78
79 {We open with createFile() the unit for write down the file in the unit. The
80 CreateFile function creates or opens objects and returns a handle that can be
81 used to access the object.}
82
83 f_hndoutput:= CreateFile(PChar(ChangeFileExt(edtUnitToCreate.Text,
84 '.pas')), GENERIC_WRITE, 0, nil, CREATE_ALWAYS,
85 FILE_ATTRIBUTE_NORMAL, 0);
86
87 {Then we call EmbedFile which opens the file to be write down in the unit. The
88 WriteFile function writes data to a file and is designed for both synchronous
89 and asynchronous operation. The function starts writing data to the file at
90 the position indicated by the file pointer. }
91
92 BOOL WriteFile(
93 HANDLE hFile, // handle to file to write to
94 LPCVOID lpBuffer, // pointer to data to write to file
95 DWORD nNumberOfBytesToWrite, // number of bytes to write
96 LPDWORD lpNumberOfBytesWritten, // pointer to bytes written
97 LPOVERLAPPED lpOverlapped );
98
99 {After the write operation has been completed, the file pointer is adjusted by the
100 number of bytes actually written. }
101
102 f_hndopen:= CreateFile(PChar(filename), GENERIC_WRITE +
103 GENERIC_READ, 0, nil, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
104
105 //Each time the file pointer is adjusted we write a block of
106
107 abuf: array[0..19] of byte;
108 Result:= ReadFile(f_hndopen, abuf, sizeof(abuf), BytesRead, nil);
109 if bytesRead > 0 then begin .....
110
111 //At least our generated unit looks like
112
113 unit dws_logo2;
114
115 interface
116
117 const
118 dws_logo_bmp: array[0..21717] of byte = (
119 $42,$4D,$D6,$54,$00,$00,$00,$00,$00,$00,$76,$00,$00,$00,$28,$00,$00,$00,$F0,$00,
120 $00,$00,$B4,$00,$00,$00,$01,$00,$04,$00,$00,$00,$00,$00,$60,$54,$00,$00,$C4,$0E,
121 $00,$00,$C4,$0E,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,$00,
122 ..............
Conclusion:
You do have 3 possibilites to embed files:
1. Go the way with resources / resource workshop
2. Go to VCL streaming is based on TComponent and TStream with write and read
3. Go with this article is more generic the advantage is transparency at design
time and protection at runtime of the embedded files, you can even use binaries
which you control with an inline assembler format.
The app the Hexer is downloadable
http://www.softwareschule.ch/download/hexer2.zip
|