如何禁用菜单项并停止 ActionMainMenuBar 中的下拉菜单?

How to disable menuitem and stop dropdown in ActionMainMenuBar?

Delphi 10.4.2 我的 TActionMainMenuBar 有问题。当我在代码中禁用一个菜单项时,它显示为禁用,但如果我下拉它旁边的一个启用的菜单项,然后移动到禁用的菜单项,它的子菜单就会下拉! 如果这不是错误,是否有办法防止禁用的菜单项掉落?

谢谢 托尼

一个简单的解决方案是在禁用项目时关闭 TActionMainMenuBar.OnPopup 事件中的菜单:

procedure TForm1.ActionMainMenuBar1Popup(Sender: TObject; Item: TCustomActionControl);
begin
  if not Item.Enabled then
    ActionMainMenuBar1.CloseMenu;
end;

但是我不推荐这样做,因为它也会退出菜单循环,这可能会导致糟糕的用户体验。

您描述的行为可以被视为缺陷,您可以 report it to Embarcadero. To fix that in your code you should override method CreatePopup of TActionMainMenuBar to prevent creating popup menus (return nil) for disabled items. But returning nil in that method will cause another problem (access violation) when opening submenu using or on keyboard. Therefore you should handle that case too by patching WMKeyDown. Ideally you should derive your own class from TActionMainMenuBar or use an interposer class:

type
  TActionMainMenuBar = class(Vcl.ActnMenus.TActionMainMenuBar)
  private
    procedure WMKeyDown(var Message: TWMKeyDown); message WM_KEYDOWN;
  protected
    function CreatePopup(AOwner: TCustomActionMenuBar;
      Item: TCustomActionControl): TCustomActionPopupMenu; override;
  end;

{ ... }


function TActionMainMenuBar.CreatePopup(AOwner: TCustomActionMenuBar;
  Item: TCustomActionControl): TCustomActionPopupMenu;
begin
  if Item.Enabled then
    Result := inherited CreatePopup(AOwner, Item)
  else
    Result := nil;
end;

procedure TActionMainMenuBar.WMKeyDown(var Message: TWMKeyDown);
begin
  if Assigned(Selected) and (not Selected.Control.Enabled) and
     (Orientation in [boLeftToRight, boRightToLeft]) and
     (Message.CharCode in [VK_UP, VK_DOWN]) then
    Exit; { do not try to popup disabled items }
  inherited;
end;