Подтвердить что ты не робот

Как я могу узнать, кто вызвал действие в Delphi?

Когда срабатывает событие TAction, "Отправитель" всегда является самим действием. Обычно это самое полезное, но можно ли как-нибудь выяснить, кто вызвал событие OnExecute?

Пример

Допустим, у вас есть форма со следующим:

  • 2 кнопки, называемые Button1 и 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

Example.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(), но этот вид не поддается всей цели использования действий в первое место.

Я также не хочу иметь отдельное действие для каждого отдельного элемента управления. Приведенный выше пример является упрощенной версией проблемы, с которой я сталкиваюсь. У меня есть меню с переменным количеством пунктов меню (имен файлов), и каждый пункт меню в основном должен делать то же самое, за исключением загрузки другого файла. Иметь действия для каждого пункта меню было бы немного глупо.

4b9b3361

Ответ 1

Попробуйте использовать свойство ActionComponent :

Хранит клиентский компонент, который вызвал выполнение этого действия.

Используйте ActionComponent, чтобы определить, какой клиентский компонент вызвал выполнение этого действия. Например, проверьте ActionComponent в обработчике событий OnExecute, если вам нужно знать, какое действие пользователя вызвало это действие.

Когда пользователь щелкает элемент управления клиента, этот клиент устанавливает ActionComponent перед вызовом действия Выполнить метод. После выполнения действия оно сбрасывает ActionComponent на ноль.

Например:

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

Используя это, я получаю "Button1" и "Button2", когда я нажимаю первую и вторую кнопку соответственно.

Ответ 2

Зная, какая кнопка запускает вид действия, идет против точки использования действий - действие может быть вызвано нажатием кнопки или щелчком по меню или любым количеством других действий пользователя. Существуют действия для унификации управления включением/отключением и обработкой кликов между кнопками и меню.

Если вы хотите узнать, какая кнопка запустила действие, потому что вы хотите выполнить несколько другую операцию или "привнести" операцию по-другому, то, возможно, TAction не подходит для того, что вы хотите сделать.

Ответ 3

Вместо действий просто используйте событие click. Установите все кнопки для использования одного и того же обработчика событий. В идеале НЕ Именоваться после первой кнопки (вы можете переименовать ее).

Здесь код:

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

Существуют ситуации, когда одно и то же действие должно применяться к аналогичным элементам управления. Проблема с

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

заключается в том, что когда действие вызывается всплывающим меню say, вы получаете имя всплывающего меню. Вы можете использовать:

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

Хорошо, пока я думаю, что нашел работоспособное решение.

Я могу иметь все элементы управления, использующие одно и то же действие; Мне просто нужно переопределить обработчик событий 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

установите метку кнопок как 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;