欧美性猛交黑人xxxx,成人毛片一区二区三区,久久综合九色综合精品,男的把j放进女人下面视频免费

動態加載和動態注冊類技術的深入探索

  • 發布于:2023-12-17
  • 193 人圍觀
Delphi的包是Delphi IDE的核心技術,沒有包也就沒有了Delphi的可視化編程。包也可以用在我們開發的項目中,其好處是可以代碼共享,減小工程尺寸,單純通過替換包文件就能實現工程的升級和補丁。但是我們要加載包,就要知道包中已經存在的類。關于如何動態加載包的資料比比皆是我就不想就此問題討論了。但是Delphi的IDE很是特殊,它無需事先知道你的包有哪些類就能注冊組建,創建組建。但是Borland沒有公開BPL文件的格式。我們自己是否可以實現IDE的功能呢?
首先我們知道。一個組件包想要能在IDE中使用就要進行注冊也就是要創建一個過程例如:
Procedure Register;
Begin
RegisterComponents(IDE中的頁面, [組件類]);
End;
在IDE加載時就要調用這個過程進行注冊。
其次我們通過Borland的文檔又知道BPL只是一種特殊格式的DLL文件。那么既然IDE可以調用得到注冊過程那么注冊過程一定要是導出類型(exports)的才行。既然如此我們可以想辦法弄明白。寫一個包文件。里面包含Test、和TestBtn兩個單元。兩個單元分別都有注冊過程,然后編譯成BPL文件。好了我們可以用EXESCOPE這個工具來弄清楚其中的奧秘。

我們可以看到一個函數@Test@Register$qqrv。幾乎可以肯定這個函數就是BPL把Test單元中的Register導出的注冊函數,而那個@Testbtn@Register$qqrv就一定是Testbtn這個單元的注冊函數??梢宰鲆粋€實驗來證明我們的想法,在Test單元的Register的函數中加上ShowMessage(‘你好,你調用了注冊函數’);
然后在我們來調用一下包中的函數@Test@Register$qqrv,隨便寫一個工程看看是不是可以調用得到Test單元中的Register過程。
var
H : Integer;
regproc : procedure();
begin
H := 0;
H := LoadPackage(''''TestPackage.bpl'''');
try
if H <> 0 then
begin
RegProc := GetProcAddress(H,''''@Test@Register$qqrv'''');//載入包中的函數
if Assigned(RegProc) then
begin
regproc();//調用函數
end;
end;
finally
if H <> 0 then
begin
UnloadPackage(H);
H := 0;
end;
end;
end;
調用的結果,果然調用到了包中Terst單元的Register過程。但是如何得到注冊了哪些類呢?注冊組件要用RegisterComponents函數。好在VCL體系的源代碼是開放的,我們看看RegisterComponents是如何實現的吧。
在Classes單元我們可以看到:
procedure RegisterComponents(const Page: string;
const ComponentClasses: array of TComponentClass);
begin
if Assigned(RegisterComponentsProc) then
RegisterComponentsProc(Page, ComponentClasses)
else
raise EComponentError.CreateRes(@SRegisterError);
end;
畫線的是一個函數指針,Delphi的IDE就是在這個指針所指的函數里去作具體的工作。我們也可以利用它來實現我們的注冊。
procedure MyRegComponentsProc(const Page: string;
const ComponentClasses: array of TComponentClass);
var
I : Integer;
IDEInfo : PIDEInfo;
begin
for i := 0 to High(ComponentClasses) do
begin
RegisterClass(ComponentClasses[I]);
end;
end;
然后一條語句RegisterComponentsProc:= @MyRegComponentsProc;似乎就解決問題了。
慢著!RegisterComponentsProc是在Classes單元。但是BPL中的Classes單元是在另一個運行時的包VCL.BPL里面。而我們工程所修改的RegisterComponentsProc的指針是編譯在我們的工程中,空間是不同的。所以我們的工程一定要編譯成帶運行時包VCL.BPL的才行。但是這樣一來的話我們也就只能載入和我們所用的編譯器相同版本編譯器編譯出來的BPL文件了,也就是說Delphi6只能載入Delphi6或者BCB6編譯出來的BPL文件以此類推。
但是還有一個問題沒有解決,那就是如何知道一個包中到底有那些各單元呢?可以通過GetPackageInfo過程來獲得。
我已經把加載包的過程封裝到了一個類中。整個程序的代碼如下:

{ *********************************************************************** }
{ }
{ 動態加載Package的類 }
{ }
{ wr960204(王銳)2003-2-20 }
{ }
{ *********************************************************************** }
unit UnitPackageInfo;

interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
PIDEInfo = ^TIDEInfo;
TIDEInfo = record
iClass: TComponentClass;
iPage: string;
end;
type
TPackage = class(TObject)
private
FPackHandle: THandle;
FPackageFileName: string;
FPageInfos: TList;
FContainsUnit: TStrings; //單元名
FRequiresPackage: TStrings; //需要的的包
FDcpBpiName: TStrings; //
procedure ClearPageInfo;
procedure LoadPackage;
function GetIDEInfo(Index: Integer): TIDEInfo;
function GetIDEInfoCount: Integer;
public
constructor Create(const FileName: string); overload;
constructor Create(const PackageHandle: THandle); overload;
destructor Destroy; override;
function RegClassInPackage: Boolean;

property IDEInfo[Index: Integer]: TIDEInfo read GetIDEInfo;
萬企互聯
標簽: