16

TAction イベントが発生すると、「送信者」は常にアクションそのものです。通常はこれが最も便利ですが、アクションの OnExecute イベントをトリガーしたのは誰かを特定することはできますか?

次のフォームがあるとします。

  • Button1と呼ばれる 2 つのボタンButton2
  • 1 TAction が呼び出されましたactDoStuff

両方のボタンに同じアクションが割り当てられます。クリックしたボタンを表示することはできますか?

Example.dfm

object Form1: TForm1
  object Button1: TButton
    Action = actDoStuff
  end
  object Button2: TButton
    Action = actDoStuff
    Left = 100
  end
  object actDoStuff: TAction
    Caption = 'Do Stuff'
    OnExecute = actDoStuffExecute
  end
end

例.pas

unit Example;
interface
uses Windows, Classes, Forms, Dialogs, Controls, ActnList, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    actDoStuff: TAction;
    procedure actDoStuffExecute(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation    
{$R *.dfm}

procedure TForm1.actDoStuffExecute(Sender: TObject);
begin
  ShowMessage('Button X was clicked');
end;

end.

現時点で唯一の解決策は、ボタンのアクション プロパティを使用せず、ボタンごとにイベント ハンドラを用意し、そこから actDoStuffExecute() を呼び出すことですが、それはそもそもアクションを使用する目的全体に反するものです。

個別のコントロールごとに専用のアクションも必要ありません。上記の例は、私が直面している問題の単純化されたバージョンです。さまざまな数のメニュー項目 (ファイル名) を持つメニューがあり、別のファイルをロードすることを除いて、各メニュー項目は基本的に同じことを行う必要があります。メニュー項目ごとにアクションを用意するのは少しばかげています。

4

7 に答える 7

30

ActionComponentプロパティを使用してみてください。

このアクションの実行の原因となったクライアント コンポーネントを格納します。

ActionComponentを使用して、このアクションを実行させたクライアント コンポーネントを特定します。たとえば、どのユーザー アクションがこのアクションをトリガーしたかを知る必要がある場合は、 OnExecuteイベント ハンドラーからActionComponentを調べます。

ユーザーがクライアント コントロールをクリックすると、そのクライアントはアクションのExecuteメソッドを呼び出す前にActionComponentを設定します。アクションの実行後、アクションはActionComponentを nil にリセットします。

例えば:

  ShowMessage( (Sender as TAction).ActionComponent.Name );

これを使用して、最初と 2 番目のボタンをクリックすると、それぞれ「Button1」と「Button2」が表示されます。

于 2010-07-21T20:43:03.523 に答える
10

どのボタンがアクションをトリガーしたかを知ることは、アクションを使用するという点に反します。アクションは、ボタンのクリック、メニューのクリック、またはその他のユーザー アクティビティによってトリガーされる可能性があります。ボタンとメニュー間の有効/無効の状態管理とクリック処理を統一するためのアクションが存在します。

わずかに異なる操作を実行したい、または操作を別の方法で「味付け」したいために、どのボタンがアクションを起動したかを知りたい場合は、おそらく TAction は、実行したいことに対する適切なソリューションではありません。

于 2010-07-21T19:19:08.687 に答える
3

アクションの代わりに、クリック イベントを使用します。すべてのボタンが同じイベント ハンドラーを使用するように設定します。理想的には、最初のボタンにちなんで名付けないでください (名前を変更できます)。

コードは次のとおりです。

Procedure TMyForm.DestinationButtonClickHandlerThing(Sender: TObject); 
begin
  if Sender = Btn_ViewIt then
  begin
    // View It
  end
  else if Sender = Btn_FaxIt then
  begin
    // Fax It
  end
  else if Sender = Btn_ScrapIt then
  begin
    // Scrap It
  end
  else 
    ....   // error
   ...
end;
于 2010-07-21T20:10:20.450 に答える
1

同じアクションを同様のコントロールに適用する必要がある状況があります。問題は

ShowMessage( (Sender as TAction).ActionComponent.Name );

アクションがポップアップメニューによって呼び出されると、ポップアップメニューの名前が取得されます。あなたが使用することができます:

procedure TMyForm.actMyActionExecute(Sender: TObject);
var
  LMyControl: TMyControl;
begin
  if Screen.ActiveControl.Name = 'MyControl1' then
    LMyControl = Sender as TMyControl
  else
    Exit;
  // Use the local variable for whatever needed
end;
于 2014-01-31T00:18:57.407 に答える
0

ボタンのタグを1、2、...などに設定してから:

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.OnClick := ButtonClick;
  Button2.OnClick := ButtonClick;
end;

procedure TForm1.ButtonClick(Sender: TObject);
begin
  if Sender is TButton then
  begin
    Caption := 'Button: ' + IntToStr(TButton(Sender).Tag);
  end;  
end;
于 2010-07-21T19:41:01.003 に答える
0

わかりました、その間、私は実行可能な解決策を見つけたと思います..

すべてのコントロールに同じアクションを使用させることができます。OnClick イベント ハンドラーをオーバーライドする必要があるだけで、それらすべてに対して 1 つのハンドラーが必要なだけです。

どのコントロールがアクションをトリガーしたかを知ることができるかどうかはまだ知りたいのですが、現在のアプリケーションでは、以下のコードに似たソリューションを使用しています。

unit Example;

interface

uses
  Windows, Classes, Forms, Dialogs, Controls, ActnList, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    actDoStuff: TAction;
    procedure actDoStuffExecute(Sender: TObject);
    procedure ButtonClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.actDoStuffExecute(Sender: TObject);
begin
  ShowMessage('Button '+TControl(Sender).Name +' was clicked')
end;

procedure TForm1.ButtonClick(Sender: TObject);
begin
  actDoStuffExecute(Sender)
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  Button1.OnClick := ButtonClick;
  Button2.OnClick := ButtonClick
end;

end.
于 2010-07-21T19:11:53.530 に答える