⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 user_guide.html

📁 Delphi 资源文件的使用控件
💻 HTML
📖 第 1 页 / 共 4 页
字号:
<p>See Appendix 1 for a description of all the predefined resource types. </p>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h3><a name="Examples"></a>Examples</h3>
<h4><a name="eg1"></a>Example 1: Loading a resource file</h4>
<p>In this first example we demonstrate how to create a resource file object and 
	how to load a file into it. The following code fragment shows how this is done. 
</p>
<pre><span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  ...
<span class="pascal-kw">begin</span>
  ResFile := TPJResourceFile.Create;
  <span class="pascal-kw">try</span>
    ResFile.LoadFromFile('MyResFile.res');
    ...
    <span class="pascal-comment">// Do something with resource file object</span>
    ...
  <span class="pascal-kw">finally</span>
    ResFile.Free;
  <span class="pascal-kw">end</span>;
<span class="pascal-kw">end</span>;</pre>
<p>First we create a <em>TPJResourceFile</em> object and then use its <em>LoadFromFile</em> 
	method read a file from disk. We then process the file in some way and once 
	we are finished we free the resource file object. That's all there is to it. 
	Note that if the given file does not contain a valid 32 bit resource file an 
	exception will be raised.</p>
<p>We can also read resource data from a stream rather than loading from file 
	by using the <em>LoadFromStream</em> method of <em>TPJResourceFile</em> in place 
	of <em>LoadFromFile</em>. </p>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg2"></a>Example 2: Accessing all resources in a file</h4>
<p>In our next example we show how to scan through all the resources in a file 
	and how to list some information about each one. The following example assumes 
	we have created a resource files object <em>ResFile</em> and have loaded a resource 
	file into it (as in example 1). We also assume that the form contains a memo 
	named <em>Memo1</em>. Here is the code: </p>
<pre><span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  ResEntry: TPJResourceEntry;
  EntryIdx: Integer;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Assume ResFile contains a loaded resource file</span>
  ...
  Memo1.Clear;
  <span class="pascal-kw">for</span> EntryIdx := 0 <span class="pascal-kw">to</span> Pred(ResFile.EntryCount) <span class="pascal-kw">do</span>
  <span class="pascal-kw">begin</span>
    ResEntry := ResFile.Entries[EntryIdx];
    Memo1.Lines.Add(
      Format(
        'Type: "%s"   Name: "%s"   LanguageID: %0.4X',
        [ResIDToStr(ResEntry.ResType), ResIDToStr(ResEntry.ResName),
        ResEntry.LanguageID]
      )
    );
  <span class="pascal-kw">end</span>;
  ... 
  <span class="pascal-comment">// Don't forget to free ResFile at some stage.</span>
<span class="pascal-kw">end</span>;</pre>
<p>This code uses both <em>TPJResourceFile</em> and <em>TPJResourceEntry</em> 
	objects. The resource file's <em>EntryCount</em> property tells us how many 
	resources there are in the file. Each resource is represented by a <em>TPJResourceEntry</em> 
	object made available from the integer indexed <em>Entries[]</em> array property. 
	So we loop through all the valid indexes in <em>Entries[]</em> and store a reference 
	to each resource entry in turn. Having got the resource entry object we now 
	access its <em>ResType</em>, <em>ResName</em> and <em>LanguageID</em> properties 
	to get the information we want to display.</p>
<p>The details of each entry are formatted by Delphi's <em>Format</em> function 
	and added to <em>Memo1</em>. Note that we use the <em>ResIDToStr</em> helper 
	function to get a string representation of the resource type and name. We display 
	the language ID as a four digit hex number since the value is a Word.</p>
<p>You may have noticed that we have not freed any of the resource entry objects. 
	This is not necessary since they are all freed automatically when the resource 
	files object is freed (as shown in example 1). </p>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg3"></a>Example 3: Finding a resource </h4>
<p>To find a resource we use either the <em>FindEntry</em> or <em>FindEntryIndex</em> 
	methods. The difference is that <em>FindEntry</em> returns the <em>TPJResourceEntry</em> 
	object for the entry (or nil if not found) while <em>FindEntryIndex</em> returns 
	the index of the entry in the <em>Entries[]</em> property.</p>
<p>Let's assume a resource file is loaded into the <em>TPJResourceFile</em> variable 
	<em>ResFile</em>. We want to find a <code>RT_HTML</code> resource named <code>INDEX_HTML</code>. 
	The following code checks if such a resource exists and displays its data size 
	in a message box, or a message saying the reosurce doesn't exist. This first 
	version of the code uses <em>FindEntry</em>:</p>
<pre><span class="pascal-comment">// Version using FindEntry</span>
<span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  Entry: TPJResourceEntry;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Assume ResFile contains a loaded resource file</span>
  ...
  Entry := ResFile.FindEntry(RT_HTML, 'INDEX_HTML', $0809);
  <span class="pascal-kw">if</span> Assigned(Entry) <span class="pascal-kw">then</span>
    ShowMessageFmt(
      'Data size for INDEX_HTML is %d',
      [Entry.DataSize]
    )
  <span class="pascal-kw">else</span>
    ShowMessage('Can''t find resource');
  ... 
  <span class="pascal-comment">// Don't forget to free ResFile at some stage.</span>
<span class="pascal-kw">end</span>;</pre>
<p> This second version of the code shows how the same result is obtained with 
	<em>FindEntryIndex</em>:</p>
<pre><span class="pascal-comment">// Version using FindEntryIdex</span>
<span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  Entry: TPJResourceEntry;
  Idx: Integer;
<span class="pascal-kw">begin</span>
  ...
  Idx := fResFile.FindEntryIndex(RT_HTML, 'INDEX_HTML');
  <span class="pascal-kw">if</span> Idx >= 0 <span class="pascal-kw">then</span>
  <span class="pascal-kw">begin</span>
    Entry := fResFile.Entries[Idx];
    ShowMessageFmt(
      'Data size for INDEX_HTML is %d', [Entry.DataSize]
    );
  <span class="pascal-kw">end</span>
  ...
<span class="pascal-kw">end</span>;</pre>
<p>Note that we have used the &quot;short form&quot; of the <em>FindEntry</em> 
	and <em>FindEntryIndex</em> methods above: they find the first resource with 
	the given type and name, irrespective of language. The long version of the methods 
	finds a specific resource type, name and language. For example the following 
	code finds a <code>RT_HTML</code> resource named <code>INDEX_HTML</code> with 
	language $0809:</p>
<pre><span class="pascal-comment">// "Full" version of FindEntry</span>
<span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  Entry: TPJResourceEntry;
<span class="pascal-kw">begin</span>
  ...
  Entry := ResFile.FindEntryIndex(
    RT_HTML, 'HTMLRES_HTML', $0809
  );
  <span class="pascal-kw">if</span> Assigned(Entry) <span class="pascal-kw">then</span>
    ... etc ...
<span class="pascal-kw">end</span>;</pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg4"></a>Example 4: Listing specific resources from a file </h4>
<p>We can use the <em>IsMatching</em> method of <em>TPJResourceEntry</em> to check 
	if a specific resource matches given criteria. <em>IsMatching</em> can match 
	just a resource type, and resource type and name or can uniquely identify a 
	resource in a file by matching its type, name and language. Like <em>TPJResourceFile.FindEntry</em>, 
	the language ID parameter is optional. The resource name parameter can be nil 
	if we don't want to specify the name in the match.</p>
<p>Given the above description of <em>IsMatching</em>, we can list all the <code>RT_HTML</code> 
	resources in a resource file in a <em>TMemo</em> with this code:</p>
<pre><span class="pascal-kw">var</span>
  ResFile: TPJResourceFile;
  Entry: TPJResourceEntry;
  Idx: Integer;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Assume ResFile contains a loaded resource file</span>
  ...
  <span class="pascal-kw">for</span> Idx := 0 to Pred(ResFile.EntryCount) <span class="pascal-kw">do</span>
  <span class="pascal-kw">begin</span>
    Entry := ResFile.Entries[Idx];
    <span class="pascal-kw">if</span> Entry.IsMatching(RT_HTML, <span class="pascal-kw">nil</span>) <span class="pascal-kw">then</span>
      Memo1.Lines.Add(
        Format('%s', [ResIDToStr(Entry.ResName)])
      );
  <span class="pascal-kw">end</span>;
  ...
<span class="pascal-kw">end</span>;</pre>
<p>To list only all the different language versions of the <code>RT_HTML</code> 
	resource named <code>INDEX_HTML</code> we simply change the <em>IsMatching</em> 
	method call in the for loop to:</p>
<pre>Entry.IsMatching(RT_HTML, 'INDEX_HTML')</pre>
<p class="gototop"><a href="#Top">Back to top</a></p>
<h4><a name="eg5"></a>Example 5: Adding or modifying a resource's data</h4>
<p>While the code in this unit does not understand the various resource data formats 
	it does assist in reading, adding, updating and deleting the raw resource data. 
	The <em>TPJResourceEntry</em> class's <em>Data</em> object exposes the resource 
	data as a <em>TStream</em> which means that we can use normal stream handling 
	techniques to access the data.</p>
<h5>Reading the data</h5>
<p>The following code fragment shows how to read all the data from the resource 
	to a buffer.</p>
<pre><span class="pascal-kw">var</span>
  Entry: TPJResourceEntry;
  Buf: PByte;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Make sure Entry references a resource object</span>
  ...
  <span class="pascal-comment">// Create buffer of required size</span>
  GetMem(Buf, Entry.DataSize);
  <span class="pascal-kw">try</span>
    <span class="pascal-comment">// Make sure resource data stream at start</span>
    Entry.Data.Position := 0;
    <span class="pascal-comment">// Read all resource data into buffer</span>
    Entry.Data.ReadBuffer(Buf^, Entry.DataSize);
    <span class="pascal-comment">// Rewind data stream again</span>
    Entry.Data.Position := 0;
    ...
    <span class="pascal-comment">// Do something with Buf</span>
    ...
  <span class="pascal-kw">finally</span>
    <span class="pascal-comment">// Release buffer</span>
    FreeMem(Buf);
  <span class="pascal-kw">end</span>;
<span class="pascal-kw">end</span>;</pre>
<p>We first set the buffer to the required size using <em>TPJResourceEntry</em>'s 
	<em>DataSize</em> property (The <em>Data</em> property's own <em>Size</em> property 
	also gives this information). We now ensure the data stream is positioned at 
	the start (you can't assume this!) and then read al the data into the buffer 
	using <em>TStream</em>'s <em>ReadBuffer</em> method, and finally reposition 
	the stream again ready for the next use. Having processed the data in the buffer 
	in some way we finally free the buffer.</p>
<p>It may be more convenient to copy the data stream to another stream. The next 
	example illustrates this by storing the resource data in a file named 'ResEntry.dat':</p>
<pre><span class="pascal-kw">var</span>
  Entry: TPJResourceEntry;
  FS: TFileStream;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Make sure Entry references a resource object</span>
  ...
  <span class="pascal-comment">// Open stream onto new file</span>
  FS := TFileStream.Create('ResEntry.dat', fmCreate);
  <span class="pascal-kw">try</span>
    <span class="pascal-comment">// Copy resource data to file</span>
    FS.CopyFrom(Entry.Data, 0);
    Entry.Data.Position := 0;
  <span class="pascal-kw">finally</span>
    <span class="pascal-comment">// Close the file</span>
    FS.Free;
  <span class="pascal-kw">end</span>;
<span class="pascal-kw">end</span>;</pre>
<p>Here we first open a stream onto a new file. We then use <em>TStream</em>'s 
	<em>CopyFrom</em> method to copy the whole of the resource data to the file 
	stream. Note by specifying a size of 0 to the <em>CopyFrom</em> method, <em>TStream</em> 
	automatically positions the resource data stream to the start and copies the 
	whole stream, so we don't need to position it first. Once again we reset the 
	resource data stream once we are done.</p>
<h5>Deleting data</h5>
<p>It is very easy to delete all the data in a resource: simply set the data stream's 
	size to 0 as follows.</p>
<pre><span class="pascal-kw">var</span>
  Entry: TPJResourceEntry;
<span class="pascal-kw">begin</span>
  ...
  <span class="pascal-comment">// Make sure Entry references a resource object</span>
  ...
  Entry.Data.Size := 0;
  ...
<span class="pascal-kw">end</span>;</pre>
<p>Note that you must set the <em>Size</em> property of the entry's <em>Data</em> 
	property here: you can't set the <em>DataSize</em> property since it is read 
	only.</p>
<h5>Writing data</h5>
<p>We can add data to an exisiting resource simply. Let's first look at how to 
	overwrite the existing data and then show how to append data to an existing 
	resource. For the purposes of this example, assume we have a user defined resource 
	that stores some plain text. Again, Entry is a <em>TPJResourceEntry</em> object 
	that references our resource. We will replace any existing data with the text 
	&quot;Hello World&quot;.</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">// Delete any existing data</span>
  Entry.Data.Size := 0;
  <span class="pascal-comment">// Write the required text</span>
  Text := 'Hello World';
  Entry.Data.WriteBuffer(Text[1], Length(Text));

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -