我有一些代碼在運行時可以正常作業,但在 IDE 中不能正常作業。我找不到任何關于組件加載有何不同對我有幫助的檔案。
我開發了一些定義資源的組件。我還開發了一個自定義TDataModule后代來保存這些資源定義。因為我希望能夠在專案之間共享定義,所以我有一個簡單的TComponent后代,可以在其中嵌入一個TDataModule- 想法是將適當TComponent的放在表單或資料模塊上,包括嵌入的所有資源定義TDataModule。
這似乎在運行時按預期作業,但在設計器中卻沒有。
我會盡量簡潔地解釋這個操作。涉及很多代碼,但希望以下內容足以理解正在發生的事情。
有一個TDictionary用于注冊資源定義的全域。使用二進制 UUID(16 位元組陣列)作為鍵注冊定義。資源的 UUID 設定為字串表示(為了便于流式傳輸)。當設定字串值時,setter 方法會檢查自身并向上檢查它或任何Owner TComponents 是否匹配csLoading in ComponentState,以及是否臨時保存字串值。如果不是,則資源定義將自己注冊到全域字典中。(這是必要的,因為分配了一個隨機 UUID AfterConstruction,此時csLoading未設定標志,因此必須檢查父級)。
當資源定義在呼叫中完全流式傳輸時,Loaded臨時字串用于設定 UUID 并注冊資源。
TComponent包含一個定義的TDataModule基于具有以下模板代碼的根類:
type
TITIODataResourcesLoader = class(TDataModule)
...
end;
TITIODataResourcesLoaderClass = class of TITIODataResourcesLoader;
TITIOResourceInclusion = class(TComponent)
protected
_pResources: TITIODataResourcesLoader;
class function _GetModuleClass(): TITIODatResourcesLoaderClass; virtual; abstract;
public
destructor Destroy; override;
procedure AfterConstruction(); override;
end;
destructor TITIOResourceInclusion.Destroy;
begin
FreeAndNil(Self._pResources);
inherited;
end;
procedure TITIOResourceInclusio.AfterConstruction;
begin
Self._pResources:=Self._GetModuleClass().Create(Self);
inherited;
end;
我有許多資源的組件編輯器,它們允許通過列舉TDictionary該類資源的全域值來選擇資源。因此,例如,一種資源定義型別是資料庫表的定義,而另一種資源定義型別是資料庫表連接的定義。在用于定義連接的組件編輯器中,用戶可以通過選擇在 global 中注冊的任何表來選擇要連接的表TDictionary。
在一個測驗專案中,TITIODataResourcesLoader它定義了許多表型別,并且TITIOResourceInclusion包含另一個TITIODataResourcesLoader(在不同的 BPL 檔案中),然后在運行時連接編輯器(它是一個 VCL 表單)將顯示所有表,但是在設計器中,只有在測驗專案中定義的表TITIODataResourcesLoader可用。如果我打開TITIODataResourcesLoader包含在 BPL 檔案中的資源,那么其中的資源將在測驗專案的TITIODataResourcesLoader.
因此,在運行時,流式傳輸TITIOResourceInclusion似乎不會導致包含的組件TITIODataResourcesLoader被注冊,但在運行時它確實按預期作業。
所以我的問題和困惑是:設計器中組件的流式傳輸有何不同?
uj5u.com熱心網友回復:
我問“設計器中組件的流式傳輸有何不同?”
我Application.MessageBox在派生類中添加了對方法入口點的呼叫,TDataModule我可以確認在運行時我們看到以下內容:
TOuterDM.Create
TInnerDM.Create
TInnerDM.Loaded
TInnerDM.AfterConstruction
TOuterDM.Loaded
TOuterDM.AfterConstruction
這是具有 DFM 檔案的組件的正常順序。
但是在 Designer 中,我們得到:
TOuterDM.Create
TOuterDM.AfterConstruction
TInnerDM.Create
TInnerDM.AfterConstruction
TOuterDM.Loaded
這表明不是呼叫Create設計器而是呼叫CreateNew外部和內部資料模塊,然后流式傳輸外部資料模塊而不是內部資料模塊。我沒有檢查源代碼,但我希望這是因為設計器只為“根實體”流式傳輸
TDataModule通過將此代碼添加到派生組件中,我設法獲得了我想要的行為:
procedure TITIODataResourcesLoader.AfterConstruction;
begin
// Original code for the deferred load
if(not(csDesigning in Self.ComponentState)) then
begin
// Because this is a component with a DFM file, AfterConstruction is called AFTER
// the streaming is complete
Self._LoadDeferredResources();
// Any 'OnCreate' handler is called AFTER we have initialised ...
end
else
begin
// this code added to stream in the designer
if(Self.Owner is TITIOResourceInclusion ) then
InitInheritedComponent(Self, TDataModule);
end;
inherited;
end;
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/433780.html
標籤:德尔福
上一篇:delphi11中的相機權限
下一篇:當D7exe具有清單檔案時,有時表單運行時(Tbutton、Radio、復選框等)中缺少Common-Controls
