2013-03-11 37 views
1

我有witht以下事件自定義組件的TImage事件,從而導致錯誤「不存在」

private 
    { Private declarations } 
    ... 
    fOnImageClick: TNotifyEvent; 
    fOnImageMouseUp: TMouseEvent; 
    fOnImageMouseDown: TMouseEvent; 
    fOnImageMouseMove: TMouseMoveEvent; 
    fOnImageMouseEnter: TNotifyEvent; 
    fOnImageMouseLeave: TNotifyEvent; 
    fOnImageSelect: TNotifyEvent; 
    fOnImageDblClick: TNotifyEvent; 
    protected 
    ... 
    public 
    { Public declarations } 
    ... 
    published 
    ... 
    property OnImageClick: TNotifyEvent read fOnImageClick write fOnImageClick; 
    property OnImageSelect: TNotifyEvent read fOnImageSelect write fOnImageSelect; 
    property OnImageDblClick: TNotifyEvent read fOnImageDblClick write fOnImageDblClick; 
    property OnImageMouseDown: TMouseEvent read fOnImageMouseDown write fOnImageMouseDown; 
    property OnImageMouseUp: TMouseEvent read fOnImageMouseUp write fOnImageMouseUp; 
    property OnImageMouseMove: TMouseMoveEvent read fOnImageMouseMove write fOnImageMouseMove; 
    property OnImageMouseLeave: TNotifyEvent read fOnImageMouseLeave write fOnImageMouseLeave; 
    property OnImageMouseEnter: TNotifyEvent read fOnImageMouseEnter write fOnImageMouseEnter; 
    end; 

我將它們分配到的TImage,其父母爲TPanel衛生組織父TScrollBox

img:= TImage.Create(ThumbPnl); 
img.Parent:= ThumbPnl; 
img.Tag:= I; 
img.Align:= alClient; 
img.Stretch:= true; 
img.OnClick:= fOnImageClick; 
img.OnDblClick:= fOnImageDblClick; 
img.OnMouseEnter:= fOnImageMouseEnter; 
img.OnMouseLeave:= fOnImageMouseLeave; 
img.OnMouseDown:= fOnImageMouseDown; 
img.OnMouseUp:= fOnImageMouseUp; 
img.OnMouseMove:= fOnImageMouseMove; 
自定義組件

組件編譯和buld就好了。這個組件的應用程序也編譯並運行很好。如果我分配了一個OnClick事件,它會起作用。所有其他事件,如果我分配他們並嘗試運行該應用程序,我得到一個錯誤說該事件不存在

任何人都知道這是爲什麼?

+3

請給出確切的錯誤信息。不要描述錯誤消息。引用他們。逐字。 – 2013-03-11 23:44:19

回答

2

什麼是事件

Delphi中的事件是一個方法指針。方法指針基本上是兩個指針,一個指向您分配給事件的方法,另一個指向您分配的實例(對象)。

我想什麼你期待

我想你希望在你的內心對象的事件如下分配給您的外部對象的事件,並不會自動發生。

當你分配它時,你正在做指針分配。因此,要舉一個例子,你行

img.OnDblClick:= fOnImageDblClick; 

執行與價值fOnImageDblClick當時有一個指針賦值。如果是nil,img.OnDblClick將從現在開始爲nil。如果Form1.MyComponentImageClick的時候,img.OnDblClick將指向同樣的方法對同一對象從現在開始,,如果您以後更改其中fOnImageDblClick分,imgOnDblClick不會跟着...這將遺體指向同地址。如果你想改變它,你還必須通過代碼進行更改。

如果您希望發生這種情況,您可以在外部類的事件設置器中執行此操作。

首先,聲明你這樣的活動:

published 
    ... 
    property OnImageDblClick: TNotifyEvent read fOnImageDblClick write SetOnImageDblClick; 

... 
procedure TMyClass.SetOnImageDblClick(Value: TNotifyEvent); 
begin 
    FOnImageDblClick := Value; 
    //pass the new value to the inner object. 
    if Assigned(Img) then 
    Img.OnDblClick := Value; 
end; 

如果您Img內對象存在的時候,你不需要FOnImageDblClick變量,你也可以寫該屬性的getter和取值如下:

function TMyClass.GetOnImageDblClick: TNotifyEvent; 
begin 
    Result := Img.OnDblClick; 
end; 
+0

不幸的是,創建img並將所有事件分配給它的代碼snipplet在組件的受保護方法(UpdateViewer)中循環。可以有n個。這是一個圖像查看器組件。因此,我無法在setter方法中訪問它 - 是嗎?有另一種方法嗎? – JakeSays 2013-03-12 01:23:40

+0

我將img變量從本地位置移動到組件的全局位置(專用部分) - 現在非常好用! – JakeSays 2013-03-12 01:41:55

6

對於新的組件創建者,您正在犯一個相當常見的錯誤。您正在打破這條規則:

組件用戶編寫事件處理程序,組件作家「火」事件

在你的情況,你正在做的,當你作爲組件開發者不應該被賦予什麼樣的事件這樣做。這取決於組件用戶分配代碼以發生在OnClickOnDblClick等事件中。

將事件聲明爲Published和TNotifyEvent類型足夠了。

property OnSomeEvent: TNotifyEvent read FOnSomeEvent write FOnSomeEvent; 

這就是你需要做的事情來創建事件。你的工作是「開火」他們;就是讓它們發生。

這是在適當的時候在您的組件中完成的。通常,你要做的就是創建一個方法DoXXXXX,其中XXXXX是正在發生的事情。所以,你會創建

procedure TMyImage.DoSomeEvent; 
begin 
    if Assigned(FOnSomeEvent) then FOnSomeEvent(Self); 
end; 

然後,你的代碼中,當事件應該被解僱,你只需撥打DoSomeEvent

現在,如果你想增強默認事件的功能,那麼你需要重寫觸發事件的方法。

我不想這樣做,但我的經典成分TSmiley說明了這個簡單而明確:

http://tsmiley.svn.sourceforge.net/viewvc/tsmiley/

看看這個例子,你應該看到如何創建活動。

+0

+1「我討厭這樣做」以及經典的TSmiley組件。 :p – jachguate 2013-03-12 03:33:24

+0

這個問題描述了一個不同的場景。 Q中的代碼希望用戶事件在圖像事件觸發時觸發。所以需要將圖像事件設置爲組件中定義的處理程序。而他們反過來做'如果分配(FOnSomeEvent),然後FOnSomeEvent(發件人);'跳舞。 – 2013-03-12 21:46:32