代码之家  ›  专栏  ›  技术社区  ›  Wouter van Nifterick Andrey

我怎样才能知道是谁在德尔福触发了一个行动?

  •  14
  • Wouter van Nifterick Andrey  · 技术社区  · 14 年前

    当一个动作触发时,“发送者”总是动作本身。通常这是最有用的,但不知何故,是否有可能找出是谁触发了该动作的OnExecute事件?

    例子

    假设您有一个包含以下内容的表单:

    • 2个按钮,调用 Button1 Button2
    • 打电话1次 actDoStuff

    相同的操作分配给两个按钮。是否可以显示我单击的按钮?

    实例

    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
    

    案例分析

    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.
    

    目前我看到的唯一解决方案是不使用按钮的action属性,而是为每个按钮都有一个eventHandler,并从中调用actdostuffexecute(),但这种方法首先违背了使用操作的全部目的。

    我也不希望对每个单独的控件都有专门的操作。上面的示例是我所面临问题的简化版本。我有一个菜单,菜单项(文件名)的数量是可变的,每个菜单项基本上都要做相同的事情,除了加载另一个文件。对每个菜单项都进行操作是有点愚蠢的。

    6 回复  |  直到 6 年前
        1
  •  21
  •   Ian Boyd    6 年前

    尝试使用 ActionComponent 财产:

    存储导致执行此操作的客户端组件。

    使用 动作成分 识别哪个客户机组件导致执行此操作。例如,检查 动作成分 从一个 OnExecute 事件处理程序,如果您需要知道什么用户操作触发了此操作。

    当用户单击客户机控件时,该客户机设置 动作成分 在调用操作之前 Execute 方法。动作执行后,动作复位 动作成分 到零。

    例如:

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

    使用这个按钮,当我分别单击第一个和第二个按钮时,会得到“button1”和“button2”。

        2
  •  9
  •   dthorpe    14 年前

    知道哪个按钮触发了操作,这与操作的使用点不符——一个操作可能由按钮单击、菜单单击或任何数量的其他用户活动触发。存在统一启用/禁用状态管理和按钮和菜单之间单击处理的操作。

    如果你想知道是哪个按钮触发了这个动作,因为你想执行一个稍微不同的操作,或者“风格”的操作不同,那么也许是触觉不是你想做的正确的解决方案。

        3
  •  3
  •   Chris Thornton    14 年前

    不使用动作,只使用单击事件。将所有按钮设置为使用相同的事件处理程序。理想情况下,不是以第一个按钮命名(您可以重命名它)。

    代码如下:

    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;
    
        4
  •  1
  •   user3210861    11 年前

    在某些情况下,相同的操作应适用于类似的控件。问题在于

    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;
    
        5
  •  0
  •   Wouter van Nifterick Andrey    14 年前

    好吧,同时我想我找到了一个可行的解决办法。

    我可以让所有控件使用相同的操作;我只需要重写它们的onclick事件处理程序,而我只需要为所有控件使用一个处理程序。

    我仍然有兴趣知道是否可以找出触发操作的控件,但对于我当前的应用程序,我使用的解决方案与下面的代码类似:

    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.
    
        6
  •  0
  •   ioan ghip    14 年前

    将按钮的标记设置为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;
    
    推荐文章