如何在 OSX 上的应用程序名称下创建子项目菜单?

发布于 2024-12-07 21:29:21 字数 225 浏览 0 评论 0 原文

如何在下面的屏幕截图中的Project1下和Quit上方添加TMenuItem?

在此处输入图像描述

我创建了一个 TMenuBar,并选中了 UseOSMenu 属性。 我添加的第一个 TMenuItem 是主栏中的第二个 TMenuItem...

How to add TMenuItem under Project1 and above Quit on the screenshot below?

enter image description here

I have created a TMenuBar with property UseOSMenu checked.
The first TMenuItem I added is the second one in the main bar...

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

完美的未来在梦里 2024-12-14 21:29:21

您可以通过将 IItemsContainer 实现类的 TMenuBar 分配给 Application.ApplicationMenuItems 属性来完成此操作。

示例:

如果表单上有一个名为 MenuBar1 的菜单栏组件,那么您只需在表单构造函数(或 OnCreate)中调用以下代码即可。

Application.ApplicationMenuItems := Menubar1;

然后您可以使用第二个 TMenuBar 组件来定义其他菜单项。

我会向您指出有关 ApplicationMenuItems 属性的 wiki 主题,但它没有其他帮助...

http://docwiki.embarcadero.com/VCL/XE2/en/FMX.Forms.TApplication.ApplicationMenuItems

You can do this by assigning a TMenuBar of IItemsContainer implementing class to the Application.ApplicationMenuItems property.

Example:

If there was a menu bar component on the form called MenuBar1, then you would just call the following in your forms constructor (or OnCreate).

Application.ApplicationMenuItems := Menubar1;

You can then have a second TMenuBar component to define the other menu items.

I'd point you to the wiki topic on the ApplicationMenuItems property, but it has no additional help...

http://docwiki.embarcadero.com/VCL/XE2/en/FMX.Forms.TApplication.ApplicationMenuItems

音盲 2024-12-14 21:29:21

我创建了一个单元来尝试管理我想要的东西......
有了它,我可以使用特定的 TMenuItem...并将其子项目移动到应用程序子菜单...(我仍然不知道如何从头开始添加一个...)

我也使用来自穆罕默德·阿里管理分隔符...

unit uMenu;

interface

uses
FMX.Dialogs, System.SysUtils,
  FMX.Menus
{$IFDEF MACOS}
  ,Macapi.ObjectiveC,MacApi.AppKit,MacApi.Foundation,FMX.Platform.Mac
{$ENDIF}
  ;

  type
    ManageMenu = class
  private
{$IFDEF MACOS}
    class procedure FixSeparatorItemsForMenuItem (MenuItem: NSMenuItem);
    class procedure MoveItemsToMacApplicationMenu(source, target: NSMenuItem); overload;
    class procedure MoveItemsToMacApplicationMenu(index: Integer);             overload;
{$ENDIF}
  public
    class procedure FixSeparatorItemsForMac;
    class procedure MoveItemsToMacApplicationMenu(index: Integer; menu: TMainMenu); overload;
    class procedure MoveItemsToMacApplicationMenu(index: Integer; menu: TMenuBar);  overload;
  end;

implementation

{ ManageMenu }

{$IFDEF MACOS}
class procedure ManageMenu.FixSeparatorItemsForMenuItem(MenuItem:NSMenuItem);
var
  i      : Integer;
  subItem: NSMenuItem;
begin
  if (MenuItem.hasSubmenu = False) then exit;

  for i := 0 to Pred(MenuItem.submenu.itemArray.count) do
  begin
    subItem := MenuItem.submenu.itemAtIndex(i);
    if (subItem.title.isEqualToString(NSSTR('-'))= True) then
    begin
      MenuItem.submenu.removeItemAtIndex(i);
      MenuItem.submenu.insertItem(TNSMenuItem.Wrap(TNSMenuItem.OCClass.separatorItem), i);
    end
    else
    begin
      FixSeparatorItemsForMenuItem(subItem);
    end;
  end;
end;
{$ENDIF}

class procedure ManageMenu.FixSeparatorItemsForMac;
{$IFDEF MACOS}
var
  NSApp   : NSApplication;
  MainMenu: NSMenu;
  AppItem : NSMenuItem;
  i       : Integer;
{$ENDIF}
begin
{$IFDEF MACOS}
  NSApp    := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
  MainMenu := NSApp.mainMenu;
  if (MainMenu <> nil) then
  begin
    for i := 0 to Pred(MainMenu.itemArray.Count) do
    begin
      AppItem := mainMenu.itemAtIndex(i);
      FixSeparatorItemsForMenuItem(AppItem);
    end;
  end;
{$ENDIF}
end;

{$IFDEF MACOS}
class procedure ManageMenu.MoveItemsToMacApplicationMenu(source, target: NSMenuItem);
var
  iLoop, iMax: Integer;
  subItem    : NSMenuItem;
begin
  if (source.hasSubmenu = False) then exit;

  iMax := Pred(source.submenu.itemArray.count);
  for iLoop := iMax downto 0 do
  begin
    subItem := source.submenu.itemAtIndex(iLoop);
    source.submenu.removeItemAtIndex(iLoop);
    target.submenu.insertItem(subItem, 0);
  end;
  // Hide the parent
  source.setHidden(True);
end;
{$ENDIF}

{$IFDEF MACOS}
class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer);
var
  NSApp   : NSApplication;
  MainMenu: NSMenu;
  source  : NSMenuItem;
  target  : NSMenuItem;
begin
  NSApp    := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
  MainMenu := NSApp.mainMenu;
  if (MainMenu <> nil) then
  begin
    begin
      if (MainMenu.itemArray.count > 1) then
      begin
        source := mainMenu.itemAtIndex(Succ(index));
        target := mainMenu.itemAtIndex(0);
        MoveItemsToMacApplicationMenu(source, target);
      end;
    end;
  end;
end;
{$ENDIF}

class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer; menu: TMainMenu);
begin
{$IFDEF MACOS}
  MoveItemsToMacApplicationMenu(index);
{$ELSE}
//  (menu.Children[Succ(index)] as TMenuItem).Visible := False;
//  menu.RemoveObject(...);
// ... I don't knwo how to remove items on Windows ;o(((
{$ENDIF}
end;

class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer; menu: TMenuBar);
begin
{$IFDEF MACOS}
  MoveItemsToMacApplicationMenu(index);
{$ELSE}
  if (menu.ChildrenCount > Succ(index)) and (menu.Children[Succ(index)] is TMenuItem) then
  begin
//  (menu.Children[Succ(index)] as TMenuItem).Visible := False;
//  menu.RemoveObject(...);
// ... I don't knwo how to remove items on Windows ;o(((

//    menu.BeginUpdate;
//    menu.RemoveObject((menu.Children[Succ(index)] as TMenuItem));
//    menu.RemoveFreeNotify((menu.Children[Succ(index)] as TMenuItem));
//    menu.DeleteChildren;
//    (menu.Children[Succ(index)] as TMenuItem).View.Visible := False;
//    .Free;
//    (menu.Children[Succ(index)] as TMenuItem).Destroy;
//    menu.EndUpdate;
  end;
{$ENDIF}
end;

end.

它按预期工作,这就是我在 OSX 上想要的...

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  if not bAlreadyActivated then
  begin
    bAlreadyActivated := True;
    ManageMenu.FixSeparatorItemsForMac;
    ManageMenu.MoveItemsToMacApplicationMenu(0, MainMenu1);
  end;
end;

但现在,我在 Windows 上遇到问题,因为无论我尝试什么,我仍然有为 Mac 添加的菜单在 Windows 下显示...;o(

I have created a unit to try to manage what I would like...
With it, I can use a specific TMenuItem... and move its subitems to the application submenu... (I still don't know how to add one from scratch...)

I also use the answer from Mehmed Ali to manage the separators...

unit uMenu;

interface

uses
FMX.Dialogs, System.SysUtils,
  FMX.Menus
{$IFDEF MACOS}
  ,Macapi.ObjectiveC,MacApi.AppKit,MacApi.Foundation,FMX.Platform.Mac
{$ENDIF}
  ;

  type
    ManageMenu = class
  private
{$IFDEF MACOS}
    class procedure FixSeparatorItemsForMenuItem (MenuItem: NSMenuItem);
    class procedure MoveItemsToMacApplicationMenu(source, target: NSMenuItem); overload;
    class procedure MoveItemsToMacApplicationMenu(index: Integer);             overload;
{$ENDIF}
  public
    class procedure FixSeparatorItemsForMac;
    class procedure MoveItemsToMacApplicationMenu(index: Integer; menu: TMainMenu); overload;
    class procedure MoveItemsToMacApplicationMenu(index: Integer; menu: TMenuBar);  overload;
  end;

implementation

{ ManageMenu }

{$IFDEF MACOS}
class procedure ManageMenu.FixSeparatorItemsForMenuItem(MenuItem:NSMenuItem);
var
  i      : Integer;
  subItem: NSMenuItem;
begin
  if (MenuItem.hasSubmenu = False) then exit;

  for i := 0 to Pred(MenuItem.submenu.itemArray.count) do
  begin
    subItem := MenuItem.submenu.itemAtIndex(i);
    if (subItem.title.isEqualToString(NSSTR('-'))= True) then
    begin
      MenuItem.submenu.removeItemAtIndex(i);
      MenuItem.submenu.insertItem(TNSMenuItem.Wrap(TNSMenuItem.OCClass.separatorItem), i);
    end
    else
    begin
      FixSeparatorItemsForMenuItem(subItem);
    end;
  end;
end;
{$ENDIF}

class procedure ManageMenu.FixSeparatorItemsForMac;
{$IFDEF MACOS}
var
  NSApp   : NSApplication;
  MainMenu: NSMenu;
  AppItem : NSMenuItem;
  i       : Integer;
{$ENDIF}
begin
{$IFDEF MACOS}
  NSApp    := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
  MainMenu := NSApp.mainMenu;
  if (MainMenu <> nil) then
  begin
    for i := 0 to Pred(MainMenu.itemArray.Count) do
    begin
      AppItem := mainMenu.itemAtIndex(i);
      FixSeparatorItemsForMenuItem(AppItem);
    end;
  end;
{$ENDIF}
end;

{$IFDEF MACOS}
class procedure ManageMenu.MoveItemsToMacApplicationMenu(source, target: NSMenuItem);
var
  iLoop, iMax: Integer;
  subItem    : NSMenuItem;
begin
  if (source.hasSubmenu = False) then exit;

  iMax := Pred(source.submenu.itemArray.count);
  for iLoop := iMax downto 0 do
  begin
    subItem := source.submenu.itemAtIndex(iLoop);
    source.submenu.removeItemAtIndex(iLoop);
    target.submenu.insertItem(subItem, 0);
  end;
  // Hide the parent
  source.setHidden(True);
end;
{$ENDIF}

{$IFDEF MACOS}
class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer);
var
  NSApp   : NSApplication;
  MainMenu: NSMenu;
  source  : NSMenuItem;
  target  : NSMenuItem;
begin
  NSApp    := TNSApplication.Wrap(TNSApplication.OCClass.sharedApplication);
  MainMenu := NSApp.mainMenu;
  if (MainMenu <> nil) then
  begin
    begin
      if (MainMenu.itemArray.count > 1) then
      begin
        source := mainMenu.itemAtIndex(Succ(index));
        target := mainMenu.itemAtIndex(0);
        MoveItemsToMacApplicationMenu(source, target);
      end;
    end;
  end;
end;
{$ENDIF}

class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer; menu: TMainMenu);
begin
{$IFDEF MACOS}
  MoveItemsToMacApplicationMenu(index);
{$ELSE}
//  (menu.Children[Succ(index)] as TMenuItem).Visible := False;
//  menu.RemoveObject(...);
// ... I don't knwo how to remove items on Windows ;o(((
{$ENDIF}
end;

class procedure ManageMenu.MoveItemsToMacApplicationMenu(index: Integer; menu: TMenuBar);
begin
{$IFDEF MACOS}
  MoveItemsToMacApplicationMenu(index);
{$ELSE}
  if (menu.ChildrenCount > Succ(index)) and (menu.Children[Succ(index)] is TMenuItem) then
  begin
//  (menu.Children[Succ(index)] as TMenuItem).Visible := False;
//  menu.RemoveObject(...);
// ... I don't knwo how to remove items on Windows ;o(((

//    menu.BeginUpdate;
//    menu.RemoveObject((menu.Children[Succ(index)] as TMenuItem));
//    menu.RemoveFreeNotify((menu.Children[Succ(index)] as TMenuItem));
//    menu.DeleteChildren;
//    (menu.Children[Succ(index)] as TMenuItem).View.Visible := False;
//    .Free;
//    (menu.Children[Succ(index)] as TMenuItem).Destroy;
//    menu.EndUpdate;
  end;
{$ENDIF}
end;

end.

It works as expected and it is what I want on OSX...

procedure TfrmMain.FormActivate(Sender: TObject);
begin
  if not bAlreadyActivated then
  begin
    bAlreadyActivated := True;
    ManageMenu.FixSeparatorItemsForMac;
    ManageMenu.MoveItemsToMacApplicationMenu(0, MainMenu1);
  end;
end;

but now, I have an issue on Windows because whatever I try, I still have the menu I added for Mac displayed under Windows... ;o(

⊕婉儿 2024-12-14 21:29:21

从 Delphi XE7 开始,Application.ApplicationMenuItems 属性不再存在。

您现在必须创建一个 TMainMenu 项才能获得预期结果,无需分配它。只需将 TMainMenu 放到您的主窗体上并添加您的项目,它们就会出现在 OSX 应用程序菜单中。

As of Delphi XE7, the Application.ApplicationMenuItems property no longer exists.

You now have to create a TMainMenu item to get the expected result, no need to assign it. Just drop a TMainMenu on to your main form and add your items, and they will appear in the OSX application menu.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文