動的に発生したコンポのイベントハンドラ

解決


QA  2009-04-06 19:04:36  No: 33913  IP: 192.*.*.*

この掲示板にあった右寄せできる TEdit のコードを参考にして次のように
コーディングしたのですが、イベントが発生しません。どこが悪いのでしょう?
  TMyEdit = class(TEdit) //イベントがそのまま使えるようにTEditから派生
  protected              //オリジナルはTCustomEditから派生
    procedure CreateParams(var Params: TCreateParams); override;
  end;

  TForm1 = class(TForm)
  private
    procedure Dec2EditChange(Sender: TObject); //反応しないイベント
  ・・・・・・

var
  Form1: TForm1;
  DecEdit: TMyEdit;

implementation

procedure TMyEdit.CreateParams(var Params: TCreateParams);
begin
  inherited CreateParams(Params);
  Params.Style := Params.Style or ES_RIGHT;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  DecEdit := TMyEdit.Create(Form1);
 ・・・・・・

//このイベントハンドラが反応しない
procedure TForm1.Dec2EditChange(Sender: TObject);
begin
  if (Dec2Edit.Text = '') then
   ・・・・・・
end;

編集 削除
Mr.XRAY  2009-04-06 19:55:59  No: 33914  IP: 192.*.*.*

Mr.XRAYです.

>イベントが発生しません。

OnChangeを実装したいということでしょうか.
でしたらコンポーネント内部のChangeメソッドをオーバーライドします.

  protected
    procedure Change; override;

implementation


procedure TMyEdit.Change;
begin
  //inheritedを忘れずに
  inherited;
  //ここに希望の処理を書く
end;

編集 削除
Mr.XRAY  2009-04-06 19:57:40  No: 33915  IP: 192.*.*.*

動作確認環境は,Windows XP(SP3) + Delphi 7 Proです.

編集 削除
Mr.XRAY  2009-04-06 20:03:09  No: 33916  IP: 192.*.*.*

>procedure TMyEdit.Change;
>begin
>  //inheritedを忘れずに
>  inherited;
>  //ここに希望の処理を書く
>end;

この書き方ですが,目的によっては,

procedure TMyEdit.Change;
begin
  //ここに希望の処理を書く
  inherited;
end;

と書くこともあります.元の処理(inherited)を先にするか,後にするかですね.
この場合,元の処理というのは,Delphi(VCL)の基本的に必要な処理と,
もし,このコンポを登録した場合,フォームに配置した時に,定義したOnChagneイベント
のことになります.

編集 削除
Mr.XRAY  2009-04-06 20:35:13  No: 33917  IP: 192.*.*.*

ついでに,くどいようですが(笑)

イベントというのは特殊な処理なんです.
QAさんのコードのように,単にメソッドを定義してもDelphiにはそれが何であるか
理解できません.
以下のページでは,このイベントについて説明しています.

http://mrxray.on.coocan.jp/Others/A_UltraIntro01.htm

コンポーネントの内部でイベントを処理する場合,
今回の場合は,Changeメソッドをoverrideしたメソッドを作成すると,
自動的にこのメソッドを呼出してくれます.
当然ですが,overrideの指定がなければQAさんのコードと同じになって
しまいます.
このメソッド名は,関連するイベントに対してそれぞれ違うメソッドが用意
されています(ヘルプで確認できます).

イベントの定義の方法には次のように,自分で作成したメソッドを割り当てることも
できます.ただし,この方法で作成するメソッドの引数の型と順番は,元のイベント
の引数の型と順番を同じにする必要があります.

DecEdit.OnChange := XXXXX //自分で作成した任意のメソッド名

編集 削除
QA  2009-04-06 21:52:29  No: 33918  IP: 192.*.*.*

Mr.XRAYさん、丁寧なレスありがとうございます。
  マニュアルのコンポーネント開発ガイドを見ながらボチボチやっているのですが
読んでもよくわからないことが多いので、まず動かしてようすを見ています。
> OnChangeを実装したいということでしょうか.
> でしたらコンポーネント内部のChangeメソッドをオーバーライドします.
  OnChange に新しい機能を追加する必要もないし、隠したいプロパティもないので TEdit から派生してます。ですから OnChange はそのまま使えるのではないでしょうか。
  いまちょっと確認したら上のTMyEditの代わりに TEdit を動的に作成して同じようにコーディングしてみましたが、やはりイベントは発生しません。

unit main;

interface

uses
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
  StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure FormCreate(Sender: TObject);

    procedure DecEditChange(Sender: TObject); //手書きのイベントハンドラ
  private
    { Private 宣言 }
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;
  DecEdit: TEdit;

implementation

{$R *.DFM}

procedure TForm1.FormCreate(Sender: TObject);
begin
  DecEdit := TEdit.Create(self);
  with DecEdit do
  begin
    Parent := Form1;
    Visible := True;
    Font.Style := [fsBold];
    Font.Size := 11;
    Height := 23;   Width := 150;
    Left := 8;      Top := 55;
  end;
end;

//TEditでもこれは反応しない
procedure TForm1.DecEditChange(Sender: TObject);
begin
  if (DecEdit.Text = '') then
    Button1.Enabled := False
  else
    Button1.Enabled := True;
end;

end.

編集 削除
tor  2009-04-06 22:36:09  No: 33919  IP: 192.*.*.*

IDEでイベントハンドラを追加すると
「このメソッドは○○というコンポーネントの××ハンドラだ」
という関連付けを自動でやってくれますが、
動的生成した場合は自分で設定しないとだめです。
(それらしい名前を付けただけでコンパイラが自動的にやってくれるわけではありません)

DecEdit := TEdit.Create(Self);
...
DecEdit.OnChange := Self.DecEditChange;

編集 削除
QA  2009-04-06 23:07:42  No: 33920  IP: 192.*.*.*

> DecEdit.OnChange := Self.DecEditChange;
  ああ、そうなんですね。
  そうか、イベントもこんなふうに代入できるんですね。
  ほんとうにありがとうございました。
  delphiの書籍やサイトは少ないのでこの掲示板はほんとうに助かります。

編集 削除