How can I see who triggered an action in Delphi?

前端 未结 7 1331
别那么骄傲
别那么骄傲 2021-02-05 12:42

When a TAction event fires, the \"Sender\" is always the action itself. Usually that\'s the most useful, but is it somehow possible to find out who triggered the action\'s OnExe

相关标签:
7条回答
  • 2021-02-05 12:52

    Instead of actions, just use a click event. Set all buttons to use the same event handler. Ideally, NOT named after the first button (you can rename it).

    Here's the code:

    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;
    
    0 讨论(0)
  • 2021-02-05 12:58

    Try using the ActionComponent property:

    Stores the client component that caused this action to execute.

    Use ActionComponent to discern which client component caused this action to execute. For example, examine ActionComponent from an OnExecute event handler if you need to know what user action triggered this action.

    When the user clicks a client control, that client sets ActionComponent before calling the action's Execute method. After the action executes, the action resets ActionComponent to nil.

    For example:

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

    Using this I get "Button1" and "Button2" when I click the first and second button respectively.

    0 讨论(0)
  • 2021-02-05 13:02

    There are situations where the same action should apply to similar controls. The problem with

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

    is that when the action is invoked by a say popup menu, you get the popup menu's name. You could use:

    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;
    
    0 讨论(0)
  • 2021-02-05 13:05

    Ok, in the meanwhile I think I found a workable solution..

    I can have all controls use the same action; I just need to override their OnClick event handler, and I just need a single handler for all of them.

    I'm still interested to know if it's possible to find out which control triggered the action, but for my current application I'm using a solution that's similar to the code below:

    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.
    
    0 讨论(0)
  • 2021-02-05 13:08

    Knowing what button triggered the action sort of goes against the point of using actions - an action may be triggered by a button click, or a menu click, or any number of other user activities. Actions exist to unify the state management of enable/disabled and click handling between buttons and menus.

    If you want to know which button fired the action because you want to perform a slightly different operation, or "flavor" the operation differently, then perhaps TAction isn't the right solution for what you want to do.

    0 讨论(0)
  • 2021-02-05 13:08

    set the Tag of the buttons as 1, 2, ... etc and then:

    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;
    
    0 讨论(0)
提交回复
热议问题