网站公告列表

  没有公告

加入收藏
设为首页
联系站长
您现在的位置: 网络学院 >> 程序设计 >> Delphi编程 >> 文章正文
  RegisterClass            【字体:
RegisterClass
作者:佚名    文章来源:不详    点击数:    更新时间:2007-9-12    
在 2002 年 8 月我在 Programer 深度論壇中,發表了一篇關於 RegisterClass 的文章,當時是依照記憶中的印象回答網友的問題,但是沒多久就發現文章內容可能有問題,卻因為時間的因素,我無法證實文章可疑之處是否有誤,因此撰寫此文加以釐清整個 RegisterClass 的用法。
正在装载数据……
希望對這方面有興趣的人有所幫助。
RegisterClass 方法依照 Delphi v6.0 Online Help 的解釋並不清楚,只是說將 Class 的資訊利用 streaming system 來註冊的,但是並未說明註冊到何處?然而根據我刨根究底的追查發現,其實 RegisterClass 是將 Class 的資訊註冊到 RegGroups 這個 Delphi 預設物件當中的(而這個物件在程式碼中無法存取),而 RegGroups 這個物件類別的宣告是這樣子的
 
 TRegGroups = class
  private
    FGroups: TList;
    FLock: TRTLCriticalSection;
    FActiveClass: TPersistentClass;
    function FindGroup(AClass: TPersistentClass): TRegGroup;
  public
    constructor Create;
    destructor Destroy; override;
    procedure Activate(AClass: TPersistentClass);
    procedure AddClass(ID: Integer; AClass: TPersistentClass);
    function GetClass(const AClassName: string): TPersistentClass;
    function GroupedWith(AClass: TPersistentClass): TPersistentClass;
    procedure GroupWith(AClass, AGroupClass: TPersistentClass);
    procedure Lock;
    procedure RegisterClass(AClass: TPersistentClass);
    procedure RegisterClassAlias(AClass: TPersistentClass; const Alias: string);
    function Registered(AClass: TPersistentClass): Boolean;
    procedure StartGroup(AClass: TPersistentClass);
    procedure Unlock;
    procedure UnregisterClass(AClass: TPersistentClass);
    procedure UnregisterModuleClasses(Module: HMODULE);
    property ActiveClass: TPersistentClass read FActiveClass;
  end;
 
這個對於我當初說 RegisterClass 會將資訊註冊到 Windows 的 Registry 當中的說法,有相當大的出入,不過 Delphi 之前版本在 RegisterClass 的做法上,是否真如我所說的,我已無法可考證(因為我早已沒有 Delphi v2.0 以前的 Source Code 可以追蹤),不過我們卻可以針對 Delphi v6.0 以後的版本來研究一下,Delphi 到底是如何運作 Class 的資訊。
根據 Online Help 的說明,經表單所宣告要參考到的 Form 類別及 Component 類別,我們可以當作已經自動註冊過的東西。所以我們不必擔心執行時期,程式會參考不到類別的定義,因此我們用下面的例子來說明一下:
先開啟一個新的專案,並且在專案中加入兩個 Form1 及 Form2,然後在 Form1中寫下以下的程式碼:
implementation
uses Unit2;
 
{$R *.dfm}
 
procedure TFmMain.Button1Click(Sender: TObject);
begin
   RegisterClass(TForm2);
end;
 
procedure TFmMain.Button2Click(Sender: TObject);
begin
   if FindClass('TForm2') <> nil then
      ShowMessage('Found !!')
end;
 
我們發現必須在按下 Button1 註冊 TForm2 之後,再按下 Button2 程式才能找到 Form2 的定義,這個與 Online Help 說明是相符的。現在我們在 Form2 中以 TImage 放入一張很大的圖檔,然後在 dpr 檔案中移除 Unit2 單元,而後再試一次,我們發現依然可以成功。但是檢查執行檔的大小,卻發現在 dpr 專案檔移除Unit2 的前後並沒有改變,但是如果一併移除 uses 對於 Unit2 的宣告,並且 Mark 掉 RegisterClass(TForm2);  這行指令,則可以發現執行檔的大小明顯縮小了,但是執行的結果卻失敗了。這說明了 Delphi 的編譯器會因為類別參考的需要,而將類別定義的資訊,全部編譯到執行檔中。而 RegisterClass 則是將類別資訊另行註冊到 RegGroups 的物件當中罷了。
現在我們再回頭看看 RegGroups 的定義。在 RegGroups 定義中有一個 FGroups 的成員,它的型態是 TList。然後再看一下 AddClass 的成員函數
 
procedure TRegGroups.AddClass(ID: Integer; AClass: TPersistentClass);
begin
  TRegGroup(FGroups[ID]).AddClass(AClass);
end;
 
赫赫!!果然我們證明了呼叫 RegisterClass 只是另外複製一份類別資訊到 Delphi 預設的 RegGroups 當中,與執行檔中已存的類別定義並沒有關係,只是當程式結束時,我們在執行時期用 RegisterClass 所註冊的類別資訊會一併消失而已。這個與我在 Programmer 深度論壇中所說 ”使用 RegisterClass 必須保證類別定義讓程式能夠找到” 的這句話有一些出入。不過沒關係,雖然記憶這個東西,有的時候會不太可靠,但是只要凡事多驗證一下,還是可以得到正確的結果。所以到目前為止,我們可以做一個小小的結論,是在 Delphi v6 中使用 RegisterClass 並不會造成什麼樣的不良的結果。
回歸正題,從上面測試的內容中,我們可以發現一點,那就是類別的定義資料必須編譯在執行的程式碼中,才可以正確執行。這樣一來使用者在用 RegisterClass 迂迴的建立物件的方式,除了一些特殊的目的之外,似乎有一點多餘。所以如果能夠不把類別定義編譯到程式碼中,然後也能正確的建立物件,那豈不是能夠顯得出真正的價值。於是我們再回到 Source Code 中追蹤看看。我記得 TStream 類別中有一個方法是 ReadComponent,它的原型是這樣子的
var
  Reader: TReader;
begin
  Reader := TReader.Create(Self, 4096);
  try
    Result := Reader.ReadRootComponent(Instance);
  finally
    Reader.Free;
  end;
end;
 
然後 TReader 的 ReadRootComponent 原型則又是這樣子的
 
……
try
      ReadPrefix(Flags, I);
      if Root = nil then
      begin
        Result := TComponentClass(FindClass(ReadStr)).Create(nil);
        Result.Name := ReadStr;
      end else
      begin
……
end;
except
end;
……
 
我們可以發現在上面的程式段落中的 TComponentClass(FindClass(ReadStr)).Create(nil); 這行指令,其實就是在找RegGroups 物件中,是否有相對應的類別定義,所以我推論如果 RegGroups 不存在應有的類別定義,那麼 TStream.ReadComponent 的呼叫肯定會發生錯誤,事實上,經過我的實驗之後結果也的確如此。換句話說,由於 RegGroups 是存在於執行檔中,所以物件的類別定義我們可以推論是無法存在執行檔以外的地方。因此我們再退一萬步來看,當初我追蹤 RegisterClass 的目的,在於是否能夠將類別定義從執行檔中拆解出來,但是如果 Delphi 所編譯出來的執行檔,可以允許執行本身以外的類別定義,那麼豈不就是跟 Java 等具有直譯器功能的平台一樣了嗎??嗯!!基本上 Delphi 編譯出來的東西應該沒那麼偉大!!所以這個議題追蹤到這裡應該就可以停止了。因為當初希望類別定義的目的在於分割應用程式,但是分割應用程式有許多種方法,實在犯不著用這麼迂迴的方式!!
 


本文来源:http://blog.csdn.net/jian704/archive/2007/08/31/1767641.aspx
站内文章搜索 高级搜索
文章录入:admin    责任编辑:admin 
  • 上一篇文章:

  • 下一篇文章:
  • 发表评论】【加入收藏】【告诉好友】【打印此文】【关闭窗口
    最新热点 最新推荐 相关文章
     在delphi中使用xml文档有…
     初探delphi 7 中的插件编…
     delphi 2006(dexter) & …
     获得windows的版本信息。
     “序列号输入助手”源代…
     rs232串口通讯模块
     ado方式下判断数据表是否…
  • page、request、session、ap…

  • JSF 的性能远不及 JSP 或 St…

  • HashTable和HashMap; Vecto…

  • Core Java 之旅

  • iBatis一级缓存的探讨

  • Struts2学习:在struts2中集…

  • weblogic 9.1的domain配置my…

  • 保留weblogic 中jsp编译后生…

  • 浅析Spring框架下PropertyPl…

  • SPRING+STRUTS+HIBERNATE登录…

  •   网友评论:(只显示最新10条。评论内容只代表网友观点,与本站立场无关!)
    网络学院©2007 www.23book.net
    为您提供web编程,vb编程,vc编程,服务器架设管理,数据库设计等方面的知识 站长:David