当一个动作发射时,“发送者”始终是动作本身。通常这是最有用的,但是在某种程度上可以找出是谁触发了行动的onexecute事件?
示例
假设您有一张包含以下内容的表单:
Button1
和Button2
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.
我目前看到的唯一解决方案是不使用按钮的action属性,而是为每个按钮设置一个事件处理程序,并从那里调用actDoStuffExecute(),但这种做法违背了在第一名。
我也不希望每个单独的控件都有专门的操作。上面的例子是我面临的问题的简化版本。我有一个菜单,其中包含可变数量的菜单项(文件名),除了加载另一个文件外,每个菜单项基本上都要做同样的事情。对每个菜单项执行操作会有点愚蠢。
答案 0 :(得分:21)
尝试使用 ActionComponent 属性:
存储导致此操作执行的客户端组件。
使用 ActionComponent 来识别导致此操作执行的客户端组件。例如,如果您需要知道哪些用户操作触发了此操作,请从 OnExecute 事件处理程序中检查 ActionComponent 。
当用户点击客户端控件时,该客户端会在调用操作的 Execute 方法之前设置 ActionComponent 。执行操作后,操作会将 ActionComponent 重置为nil。
例如:
ShowMessage( (Sender as TAction).ActionComponent.Name );
使用此功能,当我分别单击第一个和第二个按钮时,我会得到“Button1”和“Button2”。
答案 1 :(得分:9)
知道哪个按钮触发了操作类型与使用操作相反 - 可以通过按钮单击,菜单单击或任意数量的其他用户活动触发操作。存在用于统一启用/禁用的状态管理以及按钮和菜单之间的单击处理的操作。
如果你想知道哪个按钮触发了动作,因为你想要执行稍微不同的操作,或者以不同的方式“调整”操作,那么对于你想要做的事情,TAction可能不是正确的解决方案。
答案 2 :(得分: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;
答案 3 :(得分:1)
在某些情况下,相同的操作应适用于类似的控件。
的问题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;
答案 4 :(得分:1)
我有一堆面板,我想让用户右键单击这些面板中的任何一个,然后执行“删除文件”操作。 因此,我有一个与所有这些面板关联的弹出菜单。 这是我找出右键单击哪个面板的方法:
(注意:我发表了很多评论来清楚地解释它是如何工作的。但是,如果您不喜欢它,可以将代码压缩为两行(请参阅第二个过程)。)
因此,如果您已将操作分配给该弹出菜单:
procedure Tfrm.actDelExecute(Sender: TObject);
VAR
PopMenu: TPopupMenu;
MenuItem: TMenuItem;
PopupComponent: TComponent;
begin
{ Find the menuitem associated to this action }
MenuItem:= TAction(Sender).ActionComponent as TMenuItem; { This will crash and burn if we call this from a pop-up menu, not from an action! But we always use actions, so.... }
{ Was this action called by keyboard shortcut? Note: in theory there should be no keyboard shortcuts for this action if the action can be applyed to multiple panels. We can call this action ONLY by selecting (right click) a panel! }
if MenuItem = NIL then
begin
MsgError('This action should not be called by keyboard shortcuts!');
EXIT;
end;
{ Find to which pop-up menu this menuitem belongs to }
PopMenu:= (MenuItem.GetParentMenu as TPopupMenu);
{ Find on which component the user right clicks }
PopupComponent := PopMenu.PopupComponent;
{ Finally, access that component }
(PopupComponent as TMonFrame).Delete(FALSE);
end;
如果您只有一个简单的弹出菜单(未分配操作):
procedure Tfrm.actDelHddExecute(Sender: TObject);
VAR PopupComponent: TComponent;
begin
PopupComponent := ((Sender as TMenuItem).GetParentMenu as TPopupMenu).PopupComponent;
(PopupComponent as TMonFrame).Delete(TRUE);
end;
您可以将所有代码放在一个返回TPanel的单个函数中,并像这样调用它:
procedure Tfrm.actDelWallExecute(Sender: TObject);
begin
if GetPanelFromPopUp(Sender) <> NIL
then GetPanelFromPopUp(Sender).Delete(FALSE);
end;
答案 5 :(得分:0)
好的,同时我觉得我找到了一个可行的解决方案..
我可以让所有控件使用相同的动作;我只需要覆盖他们的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)
将按钮的标记设置为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;