gpt4 book ai didi

Delphi ActionMainMenuBar 类别位置

转载 作者:行者123 更新时间:2023-12-03 18:44:28 26 4
gpt4 key购买 nike

我正在创建 带有类别的 ActionMainMenuBar 动态且一切正常,但作为 ActionMainMenuBar 对齐是 alBottom (就像底部的第二个选项菜单)当按下带有类别的按钮时,它们会显示在 ActionMainMenuBar 下方。如果空间足够,它将始终尝试在下方显示它们。
有什么方法可以将类别位置设置为上方或进行“下方空间不足”之类的技巧,它会自动在上方显示类别菜单

Picture with issue

RAD Studio 10.1,VCL
附言ToolBar 等也是如此

谢谢

最佳答案

它是 TCustomActionPopupMenu.PositionPopup单位 Vcl.ActnMenus负责将菜单定位为您的问题下方的评论所指出的。您可以使用 OnGetPopupClass 为您的主菜单自定义弹出菜单类。事件。或者您可以通过继承任何现有样式来创建自己的操作栏样式,这根本不需要太多工作。另一种选择是 Hook 方法 TCustomActionPopupMenu.PositionPopup并根据您的需要“修复”其行为。

我将扩展所有三种方法,但让我们从它们的共同点开始 - 方法修正 PositionPopup .它需要两个参数:

  • AnOwner: TCustomActionBar - 显示弹出菜单
  • 的操作栏(在您的情况下为主菜单)
  • ParentItem: TCustomActionControl - 调用弹出菜单的操作栏中的项目。

  • 特别是我们只对 AnOwner 感兴趣。与底部对齐, ParentItemTCustomMenuButton (顶级主菜单项)。这个想法是让 PositionPopup计算菜单边界矩形,然后将其向上移动自身的高度加上 ParentItem.Height .只有当最初计算的位置低于 ParentItem 时,我们才会这样做。并且上面有足够的空间。

    选项 1:自定义弹出类

    您可以使用事件 OnGetPopupClass 自定义弹出菜单类的
    TActionMainMenuBar :
    type
    TMyThemedPopupMenu = class(TThemedPopupMenu)
    protected
    procedure PositionPopup(AnOwner: TCustomActionBar; ParentItem: TCustomActionControl); override;
    end;

    procedure TMyThemedPopupMenu.PositionPopup(AnOwner: TCustomActionBar; ParentItem: TCustomActionControl);
    var
    ParentItemPosition: TPoint;
    begin
    inherited;
    if Assigned(AnOwner) and (AnOwner.Align = alBottom) and
    Assigned(ParentItem) and (ParentItem is TCustomMenuButton) then
    begin
    ParentItemPosition := ParentItem.ClientToScreen(Point(0, 0));
    if (ParentItemPosition.Y < Top) and (0 <= Top - Height - ParentItem.Height) then
    Top := Top - Height - ParentItem.Height;
    end;
    end;

    procedure TForm1.ActionMainMenuBar1GetPopupClass(Sender: TObject;
    var PopupClass: TCustomPopupClass);
    begin
    if PopupClass = TThemedPopupMenu then
    PopupClass := TMyThemedPopupMenu;
    end;

    请注意,仅当原始类为 TThemedPopupMenu 时,此实现才会将弹出类替换为您的自定义类。 .当您没有将操作管理器的样式更改为标准、XP 或其他自定义样式并且应用程序运行的平台支持主题时,就会发生这种情况。但您可以轻松扩展它以支持 TStandardMenuPopupTXPStylePopupMenu .

    选项 2:自定义操作栏样式

    我将继承 TPlatformDefaultStyleActionBars ,因为它是默认样式。如上所述,它可以基于平台创建标准样式、XP 样式或主题样式 Action 控件。我将再次只关注主题 Action 控件。此选项使用 TMyThemedPopupMenu 的实现从选项#1。
    type
    TMyActionBarStyle = class(TPlatformDefaultStyleActionBars)
    public
    function GetPopupClass(ActionBar: TCustomActionBar): TCustomPopupClass; override;
    end;

    var
    MyActionBarStyle: TMyActionBarStyle;

    function TMyActionBarStyle.GetPopupClass(ActionBar: TCustomActionBar): TCustomPopupClass;
    begin
    Result := inherited GetPopupClass(ActionBar);
    if Result = TThemedPopupMenu then
    Result := TMyThemedPopupMenu;
    end;

    procedure TForm1.FormCreate(Sender: TObject);
    begin
    ActionManager1.Style := MyActionBarStyle;
    end;

    { ... }

    initialization
    MyActionBarStyle := TMyActionBarStyle.Create;
    finalization
    MyActionBarStyle.Free;
    end.

    请注意,我在运行时在 FormCreate 中设置样式, 但你也可以将样式放入包中并通过 RegisterActnBarStyle 注册.这将允许您在设计时选择操作管理器的样式。

    选项 3: Hook TCustomActionPopupMenu.PositionPopup

    如果不想纠结各种款式,可以直接钩入 TCustomActionPopupMenu.PositionPopup使用例如 Delphi Detours Library .这将影响所有样式,因为它们的所有弹出菜单实现都继承自 TCustomActionPopupMenu .
    uses System.Types, DDetours, Vcl.Controls, Vcl.ActnMan, Vcl.ActnMenus, Vcl.ActnPopup;

    type
    TCustomActionPopupMenuAccess = class(TCustomActionPopupMenu);

    var
    TrampolinePositionPopup: procedure(const Self; AnOwner: TCustomActionBar;
    ParentItem: TCustomActionControl);

    procedure PositionPopupHooked(const Self; AnOwner: TCustomActionBar;
    ParentItem: TCustomActionControl);
    var
    PopupMenu: TCustomActionPopupMenu;
    ParentItemPosition: TPoint;
    begin
    TrampolinePositionPopup(Self, AnOwner, ParentItem);
    if Assigned(AnOwner) and (AnOwner.Align = alBottom) and
    Assigned(ParentItem) and (ParentItem is TCustomMenuButton) then
    begin
    PopupMenu := TCustomActionPopupMenu(@Self);
    ParentItemPosition := ParentItem.ClientToScreen(Point(0, 0));
    if (ParentItemPosition.Y < PopupMenu.Top) and (0 <= PopupMenu.Top - PopupMenu.Height - ParentItem.Height) then
    PopupMenu.Top := PopupMenu.Top - PopupMenu.Height - ParentItem.Height;
    end;
    end;

    initialization
    TrampolinePositionPopup := InterceptCreate(
    @TCustomActionPopupMenuAccess.PositionPopup, @PositionPopupHooked);
    finalization
    InterceptRemove(@TrampolinePositionPopup);
    end.

    关于Delphi ActionMainMenuBar 类别位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57299242/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com