2013-07-21 48 views
0

我正在開發一個組件,但我無法讓它考慮在設計時設置的屬性。Delphi XE2在運行時不考慮組件屬性

以下是組分的摘錄:

TRVEditFrame = class(TFrame) 
... 
    private 
    { Private declarations } 
     FRVEditor:TCustomRichView; 
    public 
    { Public declarations } 
     constructor Create(AOwner: TComponent); override; 
    protected 
     function GetRVEditor:TCustomRichView; 
     procedure SetRVEditor(Editor:TCustomRichView); 
    published 
     property RVEditor:TCustomRichView read GetRVEditor write SetRVEditor; 
    end; 
... 

constructor TRVEditFrame.Create(AOwner: TComponent); 
begin 
    inherited Create(AOwner); 
    SetRVEditor(FRVEditor); 
... 
end; 


function TRVEditFrame.GetRVEditor:TCustomRichView; 
begin 
    Result:=FRVEditor; 
end; 


procedure TRVEditFrame.SetRVEditor(Editor:TCustomRichView); 
begin 
    if Assigned(Editor) then begin 
     FRVEditor:=Editor; 
    end; 
end; 

我可以註冊該組件,將其置於療法形式,以及取決於設計時設定FRVEditor。

問題是當我運行應用程序時SetRVEditor()中的代碼沒有執行,因爲Editor = nil。

如果我能夠在設計時設置FRVEditor,那麼它是如何在運行時間=零?我怎樣才能解決這個問題 ?


我在這裏添加我進一步的評論,因爲對此的解釋是太長

@Kenneth,感謝您的回覆

  • TCustomRichView是管理 超文本的第三部分組件集的一部分文件,並有4個更專業的後代,你是 是正確的,TCustomRichView不應該在真正的應用程序中使用。
  • TRVEditFrame是我正在開發的組件。

我的組件背後的想法是用菜單,快捷方式,彈出菜單等來創建一個單一框架(因此組件TFrame的選擇)來管理每個TCustomRichView後代。

這正是我使用TCustomRichView的原因:我可以將4個後代中的任何一個「插入」我的組件框架。這與TDatasource的原理相同,可以與TTAble和TQuery連接(它們具有相同的祖先)。

我想爲什麼VCL沒有將RVEditor鏈接到我在設計時設置的TCustomRichView後代,原因是TFrame沒有OnCreate事件,例如TForm。

到目前爲止,我設法通過在主持TRVEditFrame的TForm.OnCreate中手動調用TRVEditFrame.SetRVEditor來解決問題,但我想知道是否有更好的方法來做到這一點,這就是爲什麼我在這裏提出建議的原因。

我知道你也可以爲TFrames創建一個OnCreate事件,也許我可以將TRVEditFrame.SetRVEditor放在那裏,但是,我想知道是否有更好的方法。

關於您評論的最後部分,我瞭解註冊程序,但考慮到組件正在開發中。當我開發組件時,我從來不會將它們安裝在IDE中,因爲我寧願將測試內容保留在「官方」之外。 我使用這種方法,只要組件準備就緒,我就會將其註冊到您提到的程序中。如果我想對同一個組件實現其他功能,我可以在測試環境中工作,並繼續使用IDE中的「官方」功能。

+3

什麼是TCustomRichView?它看起來像一個班。所以 屬性是一個參考。實際的對象在哪裏?它存在於表單上嗎?對象甚至在被用作屬性賦值的來源之前被實例化了嗎? 另外,構造函數中的SetRVEditor(FRVEditor)是 毫無意義的。擺脫它。 –

+0

@David TcustomerRichView是一個類,該屬性是對另一個要鏈接的類的引用 是的,該對象在設計時與TRVEditFrame以相同的形式丟棄。 「該對象是否在作爲屬性賦值的來源之前被實例化?」 我不確定你在這裏的意思。 TRVEditFrame.RVEditor在設計時指定。我回答了您的問題 –

+0

@pio pio:當您查看DFM(alt + F12)時,您是否看到屬性設置爲您分配的值? – AlexSC

回答

0

我的建議是更改設計,以便通過使用通知方法來引用自定義編輯器的框架組件,而不是手動設置屬性。所以,你的框架類改爲

TRVEditFrame = class(TFrame) 
... 
private 
{ Private declarations } 
    FRVEditor: TCustomRichView; 
protected 
    procedure Notification(aComponent: TComponent; aOperation: TOperation); override; 
public 
{ Public declarations } 
    constructor Create(AOwner: TComponent); override; 
public 
    property RVEditor:TCustomRichView read FRVEditor; 
end; 

通知方法的實現確實連接/斷開幀的自定義編輯器

procedure TRVEditFrame.Notification(aComponent: TComponent; 
            aOperation: TOperation); 
begin 
    inherited; 
    if aComponent is TCustomRichView then 
    if aOperation=opRemove then begin 
     if aComponent=FRVEditor then 
     FRVEditor := nil; 
    end else 
     FRVEditor := TCustomRichView(aComponent); 
end; 

我不知道如果你需要任何特殊的魔力當編輯器被設置/重置爲框架時處理,所以這個代碼不做任何特殊處理,只是在適當的時刻將組件或零分配給FRV​​Editor數據成員。

+0

這就是我一直在尋找的! –

0

您應該創建子組件。

constructor TRVEditFrame.Create(AOwner: TComponent); 
begin 
    inherited; // Create(AOwner); 
    FRVEditor := TRichView.Create(self); 
end; 

DFM流引擎可以加載已創建類的屬性,但不能有兩個理由爲你創建類:

1)DFM不知道任何特殊的調整來完成創建的組件上,像什麼應該是構造函數參數(如果有的話),使用什麼構造函數(很多),哪些niotifications和事件處理程序要附加等等。

2)DFM無法知道屬性應屬於哪種類型。例如,我發佈了TStrings oroperty - 應該創建哪個類的對象感覺? TStringsTStringListTRichEditStringListTHashedStringList?它們都是從TStrings繼承而來,因此它們中的任何一個都是DFM的不錯選擇 - 但不適用於您編寫的ocmponent。

因此,DFM流式子系統負責保存和加載對象的屬性,但創建這些對象純粹是您的責任。


我相信你也可以通過學習IDE設計師如何創造你的形式,使RVEdit一個變量而不是財產切邊角:

TRVEditFrame = class(TFrame) 
... 
    public 
    { Public declarations } 
     constructor Create(AOwner: TComponent); override; 
    published 
     var RVEditor:TCustomRichView; // just like users' forms are created by IDE 
    end; 

然後希望TFrame構造函數創建的內容這個變量爲你。但是這種設計很脆弱,因爲任何外部代碼都可以通過任何愚蠢的錯誤來做出類似MyEditFrame.RVEditor := ...的事情,並且導致內存泄漏和編輯器和框架之間所有連接連接的意外故障。

+0

TRVEditFrame的目的是創建一個可以「託管」4個TCustomRichView後代之一的組件,正如我在上面的筆記中所解釋的。如果我在構造函數中分配了FRVEditor:= TRichView.Create(self),那麼TRVEditFrame將只能用於TRichView。 –

+0

然後讓它創建任何後代,如你所願。 如果你想 - 使一個額外的發佈屬性保存所選子孫的'.ClassName'。 但是DFM流式傳輸不會爲屬性創建類,原因概述如下。 'TReader'無法知道應該有哪個類,所以它應該是你創建適當的類對象 –

+0

所以你說我必須在TForm.OnCreate中調用TRVEditFrame.SetRVEditor。我對麼 ? –