2

Delphi 2006 で、独立した TFrame 上のコンポーネントにイベント ハンドラを割り当てることができません。

TComboFrameTCombo を含むフレームがあり、Combo1これをメイン フォームのいくつかの場所で使用するとします。

TComboFrame のインスタンスをMyFrame1メイン フォームに配置し、コンボにイベント ハンドラーを割り当てたい場合はMyFrame1、フォームに配置したフレーム内の TCombo をクリックし、空の OnChangeフィールドをダブルクリックします。オブジェクト インスペクタの [イベント] タブにあります。

通常、 は次のような名前で新しいハンドラーを作成します。

procedure TMainForm.MyFrame1Combo1Change(Sender: TObject);

また、イベント ハンドラ名は、祖先 TComboFrame のコンポーネントの名前 ( Combo1) と、フォームに配置したインスタンスの名前( ) の両方から派生しMyFrame1ます。つまり、TComboFrame のそのインスタンスに固有です。次に、メイン フォームに配置したフレームの他のインスタンスに対してこれを行うと、それぞれが独自のイベント ハンドラーを取得します。

フレームのすべてのインスタンスに対して発生するイベント ハンドラーが必要な場合は、祖先フレーム自体を開いてそこで実行します。

これがどのように機能するかについての私の理解ですが、どこかで何かが間違っています。メイン フォームのフレームのいくつかのインスタンスのうち、独自のイベント ハンドラーを持つものもあれば、共通のイベント ハンドラーを持つものもあります。

procedure TDMainForm.ComboFrame1Combo1Change(Sender: TObject);

私が試したことはありませんが、いくつかのフレームで共有されているこの共通のイベント ハンドラと Delphi が持っているように見えるこのファントム リンクを壊していません。

この状態を修復するにはどうすればよいですか? また、そもそも何が原因でしょうか?

** 更新 1 **

回答を読み、少し実験した結果、次の手順で問題のあるコンポーネントを修復できることがわかりました。

1) フレームのすべてのイベント ハンドラーを削除します。
2) フレームの名前を覚えて、フレームを削除します。
3) OK であることがわかっている別のものをコピーします (つまり、「個別」の独自のイベント名を持っています)。
4)削除したものの代わりにそれを貼り付けます。
5) 元の名前に戻します。
6) イベント ハンドラを作成します。

...少なくとも、少なくとも一度はうまくいきました...

** 更新 2 **

それを解決する別の方法は、オブジェクト インスペクタの空のイベント フィールドをダブルクリックしたときに作成されるイベント ハンドラ名を新しい一意の名前で上書きし、その名前を再度ダブルクリックすることです。次に、Delphi は一意の名前で空のハンドラを作成します。

4

3 に答える 3

3

次のように、フレームに別のイベントを記述し、別の OnChange イベントが必要なときに設定します。

type
  TFrame2 = class(TFrame)
    ComboBox1: TComboBox;
    procedure ComboBox1Change(Sender: TObject);
  private
    FMyChangeEvent: TNotifyEvent;
  public
    property MyChangeEvent: TNotifyEvent read FMyChangeEvent write FMyChangeEvent
  end;

implementation

{$R *.dfm}

procedure TFrame2.ComboBox1Change(Sender: TObject);
begin
  //Your default combo behavior here
  if Assigned(FMyChangeEvent) then
    FMyChangeEvent(Self);
end;

そして、OnChange 動作に何かを追加する必要がある場所:

type
  TForm1 = class(TForm)
    MyLittleFrame: TFrame2;
  private
    procedure MyOwnCustomLittleOnChangeBehavior(Sender: TObject);
  public
    constructor Create(AOwner: TComponent); override;
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

constructor TForm1.Create(AOwner: TComponent);
begin
  inherited;
  MyLittleFrame.MyChangeEvent :=  MyOwnCustomLittleOnChangeBehavior;
end;

procedure TForm1.MyOwnCustomLittleOnChangeBehavior(Sender: TObject);
begin
  ShowMessage('42');
end;

私は通常、DFM でイベントを設定する Delphi の方法を信頼していないため、これを行います。気付かずにイベント全体を削除するのは非常に簡単です。

于 2012-04-06T01:19:38.990 に答える
1

Delphi6またはDelphi 2009でこの動作を再現することはできません。多くのフレーム(および名前を変更して追加および削除する可能性があります)で、イベントとフレームをリンクするためにデフォルトで使用されるDelphiの命名規則をだまされたり混乱させたりしたようです。以前のものと同じ名前で終わりました。

したがって、イベント ハンドラーをダブルクリックすると、以前に削除された (または名前が変更された) フレームによって作成されたものと同じ名前のイベント ハンドラーが表示されます (ただし、フレームを削除しても、古いイベント ハンドラーは削除されません。IYSWIM :)

したがって、私の答えは、フレーム名とイベント ハンドラー名をごちゃまぜにして混乱させてしまったということです。

于 2012-04-06T10:00:01.023 に答える
1

TComboリンクを解除したい をシングルクリックしOnClick、オブジェクト インスペクタでそのイベント ハンドラの割り当てをクリアしてから、イベントをダブルクリックして新しいイベント ハンドラを生成します。もちろん、生成されたイベント ハンドラー名が既に存在する場合は、それが再利用されますが、少なくともオブジェクト インスペクターは、イベントの生成時にすべてのオブジェクト名を再評価します。

もちろん、これはあまりオブジェクト指向のアプローチではありません。ファビオが提案するのは、より良い選択です。代わりにTFrameイベントを宣言することをお勧めしますが、他のイベントと同様に設計時に割り当てることができます。publishedpublic

于 2012-04-06T01:23:16.057 に答える