我在VCL应用程序中使用TActions和TButtons。将TButtons操作字段设置为现有操作集中代码。
动作执行方法如下所示:
void __fastcall MyFrame::MyActionExecute(TObject *Sender)
{
//Some action code
}将MyAction分配给名为MyBtn的TButton并查看操作ActionComponent
void __fastcall MyFrame::MyActionExecute(TObject *Sender)
{
if(MyAction->ActionComponent == MyBtn)
{
//.. action code when the MyBtn was clicked..
}
}好像挺管用的。
但是,通过编程调用MyAction的Execute方法,如下所示:
MyActionExcecute(NULL);似乎没有将ActionComponent设置为NULL,但是“仍然”使用MyBtn作为ActionCompoent。因此,即使没有单击按钮,上面的if语句也可以计算为true。
问题是,处理按钮单击和手动调用操作执行方法的正确方法是什么?
我知道我可以检查Sender参数是否为NULL,如果是,我可以假设它不是按钮。
发布于 2020-09-01 23:59:54
该操作的ActionComponent属性仅在UI控件触发该操作时通过该控件为自己在内部创建的内部TBasicActionLink对象设置。链接的Execute()方法有一个AComponent参数,控件将其Self/this指针传递给该参数,以在调用操作的Execute()方法之前设置操作的ActionComponent。
例如,VCL内部就是这样做的:
procedure TControl.SetAction(Value: TBasicAction);
begin
if Value = nil then
begin
ActionLink.Free;
ActionLink := nil;
...
end
else
begin
...
if ActionLink = nil then
ActionLink := GetActionLinkClass.Create(Self);
ActionLink.Action := Value;
...
end;
end;procedure TControl.Click;
begin
{ Call OnClick if assigned and not equal to associated action's OnExecute.
If associated action's OnExecute assigned then call it, otherwise, call
OnClick. }
if Assigned(FOnClick) and (Action <> nil) and not DelegatesEqual(@FOnClick, @Action.OnExecute) then
FOnClick(Self)
else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
ActionLink.Execute(Self) // <-- HERE
else if Assigned(FOnClick) then
FOnClick(Self);
end;function TBasicActionLink.Execute(AComponent: TComponent): Boolean;
begin
FAction.ActionComponent := AComponent; // <-- HERE
Result := FAction.Execute;
end;因此,不要直接调用OnExecute事件处理程序。这根本不会更新操作。调用操作的Execute()方法。您只需事先将操作的ActionComponent设置为空,例如:
MyAction->ActionComponent = NULL;
MyAction->Execute();文档声称:
当用户单击客户端控件时,该客户端在调用操作的
ActionComponent方法之前设置Execute。操作执行后,动作将ActionComponent重置为0 (Delphi)或NULL (C++)。
但是,只有当下一次UI控件决定为自己执行操作时,ActionComponent才不会自动重置。
https://stackoverflow.com/questions/63695008
复制相似问题