📄 user_guide.html
字号:
<span class="pascal-comment">// Position data ready for reading</span>
Entry.Data.Position := 0;
...
<span class="pascal-kw">end</span>;</pre>
<p>The only point of note here is the use of one of the normal idioms is writing
a string to a stream: we can't just do <code>WriteBuffer(Text, Length(Text))</code>,
but must either specify <code>Text[1]</code> or <code>PChar(Text)^</code>. Since
this is an attribute of <em>TStream</em> rather than the resource file code,
it is outside the scope of this document to discuss why!</p>
<p>Now let's look at how we add more text to the end of the resource data:</p>
<pre><span class="pascal-kw">var</span>
Entry: TPJResourceEntry;
Text: string;
<span class="pascal-kw">begin</span>
...
<span class="pascal-comment">// Make sure Entry references a resource object</span>
...
<span class="pascal-comment">// Move to end of existing data</span>
Entry.Data.Seek(0, soFromEnd);
<span class="pascal-comment">// Write new text</span>
Text := ' From DelphiDabbler';
Entry.Data.WriteBuffer(Text[1], Length(Text));
Text := #13#10'www.delphidabbler.com';
Entry.Data.WriteBuffer(Text[1], Length(Text));
<span class="pascal-comment">// Reposition stream to start</span>
Entry.Data.Position := 0;
...
<span class="pascal-kw">end</span>;</pre>
<p>Here we move the stream pointer to the end of the stream so the text we write
is appended to any existing data. Given the two examples above the data ends
up holding the following two lines of text:</p>
<pre>Hello World from DelphiDabbler
www.delphidabbler.com</pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg6"></a>Example 6: Adding a new resources to a file </h4>
<p>We can add a new resource to an existing file using <em>TPJResourceFile</em>'s
<em>AddEntry</em> method. The new resource must be unqiuely named within the
resource file (i.e. its combined resource type, name and language id must be
unique) otherwise an exception will be raised. There are two versions of the
<em>AddEntry</em> method - the first simply adds a new empty resource with zeroed
header properties while the second version adds a renamed copy of an existing
resource. Both versions of <em>AddEntry</em> take an optional language identifier.
If this is not specified the resource is language neutral (<em>LanguageID</em>
= 0).</p>
<p>The following code snippet adds four new resource to an existing resource file
object:</p>
<ol>
<li>An empty, language neutral, <code>RCDATA</code> resource with ordinal name
42. The <em>MemoryFlags</em> property is then set to "Discardable"
and its data is set to "Hello World"</li>
<li>A new language neutral <code>RCDATA</code> resource that is a copy of the
first entry but named <code>FORTYTWO</code>. This resource has the same <em>MemoryFlags</em>
and <em>Data</em>.</li>
<li>A new <code>RCDATA</code> resource also named <code>FORTYTWO</code> but
with language ID of $0809. Again this resource is a copy of the first resource.</li>
<li>A new empty <code>RCDATA</code> resource named 42 with language ID of $0809.</li>
</ol>
<pre><span class="pascal-kw">var</span>
ResFile: TPJResourceFile;
Entry1, Entry2,
Entry3, Entry4: TPJResourceEntry;
<span class="pascal-kw">const</span>
s42 = 'FORTYTWO';
ord42 = MakeIntResource(42);
sHello = 'Hello World';
<span class="pascal-kw">begin</span>
...
<span class="pascal-comment">// Assume ResFile references a valid object</span>
...
<span class="pascal-comment">// Create 1st entry: empty</span>
Entry1 := fResFile.AddEntry(RT_RCDATA, ord42);
<span class="pascal-comment">// now set mem flags and data</span>
Entry1.MemoryFlags := RES_MF_DISCARDABLE;
Entry1.Data.WriteBuffer(PChar(sHello)^, Length(sHello));
Entry1.Data.Position := 0;
<span class="pascal-comment">// Create 2nd entry as copy of entry 1</span>
Entry2 := fResFile.AddEntry(Entry1, s42);
<span class="pascal-comment">// Create 3rd entry as copy of entry 1 with language id</span>
Entry3 := fResFile.AddEntry(Entry1, s42, $0809);
<span class="pascal-comment">// Create 4th entry: empty with language id</span>
Entry4 := fResFile.AddEntry(RT_RCDATA, ord42, $0809);
...
<span class="pascal-comment">// Do something with the entries</span>
...
<span class="pascal-kw">end</span>;</pre>
<p>The entries we have created have the following properties:</p>
<table border="0" cellspacing="1" cellpadding="3" class="bodytableframe">
<tr>
<th align="left"> </th>
<th>Entry 1</th>
<th>Entry 2</th>
<th>Entry 3</th>
<th>Entry 4</th>
</tr>
<tr class="bodytablebody">
<th align="left">Type</th>
<td><code>RT_RCDATA</code></td>
<td><code>RT_RCDATA</code></td>
<td><code>RT_RCDATA</code></td>
<td><code>RT_RCDATA</code></td>
</tr>
<tr class="bodytablebody">
<th align="left">Name</th>
<td>42</td>
<td><code>FORTYTWO</code></td>
<td><code>FORTYTWO</code></td>
<td>42</td>
</tr>
<tr class="bodytablebody">
<th align="left">LanguageID</th>
<td>0</td>
<td>0</td>
<td>$0809</td>
<td>$0809</td>
</tr>
<tr class="bodytablebody">
<th align="left">MemoryFlags</th>
<td>$0100</td>
<td>$0100</td>
<td>$0100</td>
<td>0</td>
</tr>
<tr class="bodytablebody">
<th align="left">Data</th>
<td>"Hello World"</td>
<td>"Hello World"</td>
<td>"Hello World"</td>
<td><empty></td>
</tr>
</table>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg7"></a>Example 7: Checking is a resource exists </h4>
<p>We noted above that an exception is raised in a duplicate resource is added
to a file. To prevent this we may need to check if a resource exists and we
can do this with the <em>EntryExists</em> method of <em>TPJResourceFile</em>
as follows:</p>
<pre><span class="pascal-kw">var</span>
ResFile: TPJResourceFile;
Entry: TPJResourceEntry;
<span class="pascal-kw">begin</span>
...
<span class="pascal-comment">// Assume ResFile references a valid object</span>
...
<span class="pascal-kw">if not</span> ResFile.EntryExists(RT_RCDATA, 'FORTYTWO', $0809) <span class="pascal-kw">then</span>
Entry := ResFile.AddEntry(RT_RCDATA, 'FORTYTWO', $0809);
...
<span class="pascal-kw">end</span>;</pre>
<p>Note that the language id parameter to <em>EntryExists</em> is optional and
if ommitted the function checks if any resource with the given type and name
exists. Furthermore, specifying nil for the resource name makes the routine
check if any resource of the given type exists. So to check if a resource file
contains any <code>RCDATA</code> resources use:</p>
<pre><span class="pascal-kw">if</span> ResFile.EntryExists(RT_RCDATA, <span class="pascal-kw">nil</span>) <span class="pascal-kw">then</span>
<span class="pascal-comment">// We have RCDATA resources in the file</span></pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg8"></a>Example 8: Deleting resources</h4>
<p>We can delete all resources from a resource file simply by calling the <em>Clear</em>
method of <em>TPJResourceFile</em>. In addition to deleting the resources it
also frees all the <em>TPJResourceEntry</em> instances.</p>
<pre><span class="pascal-kw">var</span>
ResFile: TPJResourceFile;
<span class="pascal-kw">begin</span>
...
<span class="pascal-comment">// Assume ResFile is a valid resource file object</span>
...
<span class="pascal-comment">// Delete all resources</span>
ResFile.Clear;
...
<span class="pascal-kw">end</span>;</pre>
<p>A single resource can be deleted from the resource file using the <em>TPJResourceFile.DeleteEntry</em>
method. This checks if the file contains the resource and deletes it if so.
However, the resource entry object is not freed. While this behaviour may be
useful, it is not recommended. The preferred method is simply to free the resource
entry instance. Freeing a <em>TPJResourceEntry</em> object autmatically removes
it from the resource file.</p>
<p>So, to remove a single resource <em>ResEntry</em> from the resource file use
the following code:</p>
<pre><span class="pascal-kw">var</span>
Entry: TPJResourceEntry;
<span class="pascal-kw">begin</span>
...
<span class="pascal-comment">// Assume ResEntry references a valid object</span>
...
<span class="pascal-comment">// Delete the object from its resource file</span>
Entry.Free;
...
<span class="pascal-kw">end</span>;</pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg9"></a>Example 9: Saving a resource file </h4>
<p>Now that we have learned how to modify a resource file, it's time to know how
to save it. We simply use the <em>SaveToFile</em> or <em>SaveToStream</em> methods
of <em>TPJResourceFile</em>. The following code shows how to use <em>SaveToFile</em>:</p>
<pre><span class="pascal-kw">var</span>
ResFile: TPJResourceFile;
<span class="pascal-kw">begin</span>
<span class="pascal-comment">// Assume ResFile references a valid object</span>
...
<span class="pascal-comment">// Save the file to 'MyResource.res'</span>
ResFile.SaveToFile('MyResource.res');
<span class="pascal-kw">end</span>;</pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg10"></a>Example 10: A practical example </h4>
<p>Having given some contrived examples of most of the functionality in the <em>PJResFile</em>
unit, let us close by presenting a useful example that uses several of the methods
we have reviewed.</p>
<p>We will create a routine that takes a list of HTML and related files and create
a resource file which has a unique resource HTML resource for each file. Such
resources can be used for display in Internet Explorer, using the res:// protocol.
See my article "<a href="http://www.delphidabbler.com/articles.php?article=10"><!--<a href="/articles.php?article=10">-->How
to create and use HTML resource files</a>" for more information on this subject.</p>
<p>Here is the code of the routine: </p>
<pre><span class="pascal-kw">procedure</span> BuildHTMLResFile(<span class="pascal-kw">const</span> Files: TStrings;
<span class="pascal-kw">const</span> ResFileName: <span class="pascal-kw">string</span>);
<span class="pascal-kw">var</span>
ResFile: TPJResourceFile; <span class="pascal-comment">// res file object</span>
Entry: TPJResourceEntry; <span class="pascal-comment">// a resource entry</span>
ResName: string; <span class="pascal-comment">// a resource name</span>
SrcFileName: string; <span class="pascal-comment">// a source file name</span>
SrcStm: TFileStream; <span class="pascal-comment">// source file stream</span>
FileIdx: Integer; <span class="pascal-comment">// loops thru Files</span>
<span class="pascal-kw">begin</span>
<span class="pascal-comment">// Create new empty resource file object</span>
ResFile := TPJResourceFile.Create;
<span class="pascal-kw">try</span>
<span class="pascal-comment">// Loop thru all source files</span>
<span class="pascal-kw">for</span> FileIdx := 0 <span class="pascal-kw">to</span> Pred(Files.Count) <span class="pascal-kw">do</span>
<span class="pascal-kw">begin</span>
<span class="pascal-comment">// Record source file name</span>
SrcFileName := Files[FileIdx];
<span class="pascal-comment">// Get resource name from source name</span>
ResName := ExtractFileName(SrcFileName);
<span class="pascal-comment">// Ensure res name is not a duplicate</span>
<span class="pascal-kw">while</span> ResFile.EntryExists(
RT_HTML, PChar(ResName), $0809
) <span class="pascal-kw">do</span>
ResName := '_' + ResName;
<span class="pascal-comment">// Create new resource</span>
Entry := ResFile.AddEntry(
RT_HTML, PChar(ResName), $0809
);
<span class="pascal-comment">// Copy source file into resource data</span>
SrcStm := TFileStream.Create(SrcFileName, fmOpenRead);
<span class="pascal-kw">try</span>
Entry.Data.CopyFrom(SrcStm, 0);
Entry.Data.Position := 0;
<span class="pascal-kw">finally</span>
SrcStm.Free;
<span class="pascal-kw">end</span>;
<span class="pascal-kw">end</span>;
<span class="pascal-comment">// Save resource file</span>
ResFile.SaveToFile(ResFileName);
<span class="pascal-kw">finally</span>
<span class="pascal-comment">// Free resource file object</span>
ResFile.Free;
<span class="pascal-kw">end</span>;
<span class="pascal-kw">end</span>;</pre>
<p>This routine is passed a list of files that are to be included in the resource
file (as a string list). The name of the output file is also provided. We first
create a new resource file object to store the HTML resources. We then loop
through all the files in the list and add a new resource for each file. The
resource is named with the name of the file (file name only, no path). To ensure
the resource names are not duplicated we repeatedly append underscore characters
to duplicate names until they are unique. Having got a unique resource name
we create a new entry with the required name and then copy the file's contents
into the resource data. Finally we save the resource file and free the resource
file object.</p>
<p class="gototop"><a href="#Top">Back to top</a></p>
<!-- for stand-alone file -->
<p>This user guide and the software it refers to are copyright © Peter
Johnson,2004.
<a href="http://www.delphidabbler.com/">http://www.delphidabbler.com/</a>.</p>
</body>
</html>
<!-- END -->
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -