OnChangeのキャンセルをするには


ものほしあたる  2009-12-02 04:00:04  No: 36356

TEdit で OnChange イベントで
内容が変更されたときの処理をしているのですが、
起動時にファイルからデータを読みこみ
Edit に初期データを入れようとすると
OnChange イベントが発生してしまいます。

ファイルからデータを読込Editにデータを入れるまで
グローバルフラグを使ってフラグを立てて、
OnChange イベントの先頭で
フラグがたっていれば抜けるという処理をするしか
方法がないのでしょうか?

現在OnChangeイベントが多数あるので簡単な
方法があれば教えてください。


ぼるしち  2009-12-02 04:13:32  No: 36357

こんにちは。

初期データを入れる直前にOnChangeイベントをnilにセットし、
初期化が完了したらイベントを再設定すればOnChangeイベントの内容を変更せずに済むと思います。

例えば、Edit1のOnChangeイベント対して、
Edit1OnChangeという手続きが設定されていたとして

begin
  Edit1.OnChange := nil;

  {初期化の処理}

  Edit1.OnChange := Edit1OnChange;
end;

とすれば目的を達成できます。
複数のイベントを抑止したい場合はnilの代入とイベントの再設定の文が増えてしまいますが、
やってること自体は単純なので特に混乱しないと思いますし、
初期化を行う手続き以外には影響を与えないのがメリットだと思います。


  2009-12-28 23:55:21  No: 36358

初期化メソッド内で一度全てのEditのOnChengeを退避させれば良いので
以下ではどうでしょうか。

var
  Loop, Count: Integer;
  TempEvents: array of TNotifyEvent;
begin
  Count := 0;
  for Loop := 0 to Self.ComponentCount - 1 do
  begin
    if Components[Loop] is TEdit then
    begin
      SetLength(TempEvents, Count + 1);
      TempEvents[Count] := (Components[Loop] as TEdit).OnChange;
      (Components[Loop] as TEdit).OnChange := nil;
      Inc(Count); 
    end;
  end;

  { Editの変更処理 }

  Count := 0;
  for Loop := 0 to Self.ComponentCount - 1 do
  begin
    if Components[Loop] is TEdit then
    begin
      { Components配列に変化がない事が前提 }
      (Components[Loop] as TEdit).OnChange := TempEvents[Count];
      Inc(Count);
    end;
  end;

TCheckBoxのCheckedの変更でOnClickが発生する等他にも初期化時に
いちいちイベントに飛ばれると面倒な場合は何らかの形でイベントの
メソッドポインタを退避させれば良いと思います。


jazzin  2009-12-29 00:42:54  No: 36359

基本的にはぼるしちさんや邪さんと方法は同じなのですが、
以下のようにしておくと若干楽かもしれません。

type
  TEdit = class(StdCtrls.TEdit)
  private
    procedure SetInitText(const Value: string);
  public
    property InitText: string write SetInitText;
  end;

  // ↑フォームクラス宣言の上に書く

  TForm1 = class(TForm)
  ...

procedure TEdit.SetInitText(const Value: string);
var
  tmp: TNotifyEvent;
begin
  tmp := Self.OnChange;
  Self.OnChange := nil;
  try
    Self.Text := Value;
  finally
    Self.OnChange := tmp;
  end;
end;

これでTEditにInitTextプロパティが追加されるので、
Textプロパティに代入する代わりにInitTextに代入すると
イベントを発生させずにデータを入れられると思います。


※返信する前に利用規約をご確認ください。

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






  このエントリーをはてなブックマークに追加