2016-10-10 57 views
3

在運行時僅包,我已經定義了一個TFRAME後代,其出版裝載的事件:如何正確發佈活動?

type 
    TMyMethod = procedure() of object; 

    TMyFrame = class(TFrame) 
    protected 
    FOnLoaded : TMyMethod; 
    procedure Loaded(); override; 
    published 
    property OnLoaded : TMyMethod read FOnLoaded write FOnLoaded; 
    end; 

implementation 

{$R *.dfm} 

procedure TMyFrame.Loaded(); 
begin 
    inherited; 
    if(Assigned(FOnLoaded)) 
    then FOnLoaded(); 
end; 

在設計時只包,我已註冊TMyFrame組分如下:

unit uMyRegistrations; 

interface 

uses 
    Classes, uMyFrame; 

procedure Register; 

implementation 

procedure Register; 
begin 
    RegisterComponents('MyTestComponents', [ 
    TMyFrame 
    ]); 
end; 

我已經安裝了designtime包,我可以在工具選項板中找到TMyFrame,並且它的OnLoaded事件顯示在對象檢查器中。

我已經將TMyFrame拖入表單中,然後通過雙擊對象檢查器來分配OnLoaded事件。 分配事件後,我注意到每次嘗試打開Delphi中的窗體文件(它讓我打開「.pas」文件,但我不能切換到可視化設計器視圖)時出現訪問衝突錯誤消息。

enter image description here

難道我正確地發表了裝載的事件?如果是這樣,還有什麼不對?

進一步信息:

  1. 我使用德爾福2007年(不知道是不是它的問題)。
  2. 該錯誤也出現在做不同的父類相同的事情(不僅TFrame後裔)。

回答

8

更新(稍差假的)答案

你接受了我原來的答案,但我寫的是不正確的。羅布肯尼迪指出前英巴卡迪諾開發商艾倫鮑爾的article關於Assigned的話題。

Allen解釋說Assigned函數只測試方法指針中兩個指針的一個指針。 IDE在設計時通過將標記值分配給任何已發佈的方法屬性(即事件)來利用此優勢。這些標記值對於方法指針中的兩個指針之一(Assigned檢查的指針)有一個nil,並且有一個索引標識另一個指針中的屬性值。

所有這一切意味着當您在設計時致電Assigned時,返回False。只要您在調用它們之前檢查已發佈的方法指針Assigned,那麼您在設計時就不會調用它們。

所以我最初寫的不可能是真的。

所以我挖得更深一點。我用下面的代碼非常簡單,與XE7測試:

type 
    TMyControl = class(TGraphicControl) 
    protected 
    FSize: Integer; 
    procedure Loaded; override; 
    end; 

.... 

procedure TMyControl.Loaded; 
begin 
    inherited; 
    FSize := InstanceSize; 
end; 

.... 

procedure Register; 
begin 
    RegisterComponents('MyTestComponents', [TMyControl]); 
end; 

這足以在設計時,只要在執行Loaded方法導致IDE的AV。

我的結論是,當流式傳輸時IDE會執行一些非常不直觀的事情,並且當調用Loaded方法時,您的對象不適合使用。但我並沒有比這更好的理解。


原件(很假的)答案

你不能執行在設計時的事件處理程序,並將您的代碼就是這樣做的。原因是在設計時事件處理程序的代碼不可用。

控件的代碼是可用的,IDE已經加載它 - 但實現事件處理程序的代碼不是。該代碼不是設計時間包的一部分,它是當前在IDE中打開的項目的一部分。畢竟,它甚至可能還沒有編譯!

Loaded方法應該抵禦這種像這樣:

procedure TMyFrame.Loaded(); 
begin 
    inherited; 
    if not (csDesigning in ComponentState) and Assigned(FOnLoaded) then 
    FOnLoaded(); 
end; 
+2

的'Assigned'功能應該防止已。 [在設計時,IDE將事件處理程序設置爲一個特殊值,以便知道在DFM資源中寫入什麼,但是'Assigned'將被認爲是未分配的。](http://community.embarcadero.com/blogs/entry/assigned-or-not-assigned-that-the-question-28836)除非'Loaded'引發事件處理程序有什麼特別之處,否則我認爲這個問題更多。 –

+0

@RobKennedy我認爲你是對的,非常感謝你。我認爲還有更多事情要做。我不能完全解釋它,但是我可以從'Loaded'方法中重現問題,而不需要對'Assigned'進行任何測試,也不需要任何方法指針。 –

+0

我接受了你的回答,因爲添加「not(csDesigning in ComponentState)」條件已經解決了AV錯誤,我認爲這是我在設計時爲什麼有AV的主要原因。 根據您的更新回答,「分配(...)」條件足夠用於「正常」事件。我已經檢查過TCustomForm.DoShow事件,我可以確認你說的是什麼,它會觸發OnShow事件,如「如果分配(FOnShow)然後FOnShow(Self);」。我會問一些關於如Loaded等方法執行事件的具體問題。感謝您更新了您的答案。 – ExDev