1

次のイベントのないカスタムコンポーネントがあります

 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;

親がTPanelで親がTScrollBoxであるTImageにそれらを割り当てます

 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;

コンポーネントはコンパイルされ、正常にビルドされます。このコンポーネントを備えたアプリケーションもコンパイルされ、正常に実行されます。OnClickイベントを割り当てると、機能します。他のすべてのイベントを割り当ててアプリを実行しようとすると、イベントが存在しないというエラーが表示されます

誰もがそれがなぜであるか知っていますか?

4

2 に答える 2

6

あなたは、新しいコンポーネントの作成者にとってかなり一般的な間違いを犯しています。あなたはこのルールを破っています:

コンポーネントユーザーはイベントハンドラーを作成し、コンポーネントライターはイベントを「起動」します

あなたの場合、あなたがしていることは、コンポーネント開発者としてあなたがそれをするべきではないときにイベントを割り当てることです。OnClick、、OnDblClickなどのイベントで発生するコードを割り当てるのは、コンポーネントユーザーの責任です。

イベントを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/

その例を見ると、イベントを作成する方法がわかります。

于 2013-03-12T01:12:32.090 に答える
2

イベントとは

Delphiのイベントはメソッドポインタです。メソッドポインタは基本的に2つのポインタであり、1つはイベントに割り当てるメソッドを指し、もう1つは割り当てるライブインスタンス(オブジェクト)を指します。

私はあなたが期待していると思います

内側のオブジェクトのイベントが外側のオブジェクトに割り当てられたイベントの後に続くことを期待していると思いますが、それは自動的には発生しません。

あなたがそれを割り当てるとき、あなたはポインタの割り当てをしているのです。例を挙げると、あなたのライン

img.OnDblClick:= fOnImageDblClick;

その時点での値を使用してポインタの割り当てを実行しますfOnImageDblClick。もしそうならnilimg.OnDblClickこれからになりnilます。がその時点を指している場合、これから同じオブジェクトの同じメソッドを指します、後でfOnImageDblClickが指す場所を変更すると、imgOnDblClickは続きません...同じ古いアドレスを指し続けます。変更したい場合は、コードでも変更する必要があります。Form1.MyComponentImageClickimg.OnDblClick

それを実現したい場合は、外部クラスのイベントセッターでそれを行うことができます。

まず、次のようにイベントを宣言します。

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に、プロパティのゲッターを記述して、内部オブジェクトから直接値を取得することもできます。

function TMyClass.GetOnImageDblClick: TNotifyEvent;
begin
  Result := Img.OnDblClick;
end;
于 2013-03-12T00:00:45.887 に答える