Mac开发_NSMenu

发布时间 2023-03-25 22:03:32作者: CH520

1、创建

  • 1.1 创建配置

@property(nonatomic, strong) NSMenu *cus_menu;

// 创建
_cus_menu = [[NSMenu alloc] init];
// 设置标题
_cus_menu.title = @"23456";

NSMenuItem *menu_item = [[NSMenuItem alloc] initWithTitle:@"Open" action:@selector(menu_Clicked:) keyEquivalent:@""];
// 此方法用于将一个新的NSMenuItem插入到NSMenu中的指定位置。
[_cus_menu insertItem:menu_item atIndex:0];

menu_item = [[NSMenuItem alloc] initWithTitle:@"Open Recent..." action:nil keyEquivalent:@""];
// 该方法向菜单中添加一个新的菜单项(NSMenuItem对象)。
[_cus_menu addItem:menu_item];

// 设置子菜单项
menu_item.submenu = [[NSMenu alloc] init];
NSMenuItem *m_item = [[NSMenuItem alloc] initWithTitle:@"File1" action:@selector(menu_Clicked:) keyEquivalent:@""];
[menu_item.submenu addItem:m_item];
m_item = [[NSMenuItem alloc] initWithTitle:@"File2" action:@selector(menu_Clicked:) keyEquivalent:@""];
[menu_item.submenu addItem:m_item];

// 指定位置插入一个带有标题、动作和快捷键的菜单项。
m_item = [_cus_menu insertItemWithTitle:@"Close" action:@selector(menu_Clicked:) keyEquivalent:@"k" atIndex:2];
// 添加一个带有标题、动作和快捷键的菜单项。
m_item = [_cus_menu addItemWithTitle:@"Close_2" action:@selector(menu_Clicked:) keyEquivalent:@"j"];

// 从菜单中删除指定索引位置的菜单项。
[_cus_menu removeItemAtIndex:0];
// 从菜单中删除指定的菜单项。
[_cus_menu removeItem:menu_item];
// 为指定的菜单项设置子菜单。
[_cus_menu setSubmenu:menu_item.submenu forItem:m_item];
// 从菜单中删除所有菜单项。
[_cus_menu removeAllItems];


- (IBAction)popButtonClicked:(id)sender {
    
    NSButton *button = (NSButton *)sender;
    NSPoint point = button.frame.origin;
    point.x += button.frame.size.width;
    point.y = point.y ;
    [self.cus_menu popUpMenuPositioningItem:nil atLocation:point inView:self.window.contentView];
}

- (void)menu_Tap {
    
}

- (void)menu_Clicked:(NSMenuItem *)m_item {
    
}
  • 1.2 外观设置

// 设置菜单栏的可见性的。
[NSMenu setMenuBarVisible:YES];
// 获取菜单栏的可见性
BOOL menuBarVisible = [NSMenu menuBarVisible];
GCLog(@"menuBarVisible == %@", @(menuBarVisible))

// 如果为true,则菜单项将自动启用或禁用,具体取决于其目标的状态。如果为false,则所有菜单项都将保持启用状态。
_cus_menu.autoenablesItems = YES;
// 指定菜单的最小宽度
_cus_menu.minimumWidth = 600;
// 指定菜单的字体大小
_cus_menu.font = [NSFont boldSystemFontOfSize:25];
// 指定是否允许上下文菜单插件。
_cus_menu.allowsContextMenuPlugIns = YES;
// 指定是否显示菜单项的状态列
_cus_menu.showsStateColumn = NO;
// 指定菜单的用户界面布局方向,可以是从左到右或从右到左。
_cus_menu.userInterfaceLayoutDirection = NSUserInterfaceLayoutDirectionRightToLeft;
  • 1.3 查找查看

// 表示此菜单所属的上级菜单。也就是说,如果一个菜单作为另一个菜单的子菜单,那么它的supermenu属性就指向它的父菜单。
// 如果一个菜单没有上级菜单,那么它的supermenu属性就为nil。
NSMenu *supermenu = _cus_menu.supermenu;
GCLog(@"supermenu == %@", supermenu.title)

NSArray<NSMenuItem *> *itemArray = _cus_menu.itemArray;
GCLog(@"itemArray == %@", itemArray)
for (NSMenuItem *item in itemArray) {
    NSString *title = item.title;
    GCLog(@"title == %@", title);
    NSMenu *submenu = item.menu;
    NSArray *subsubitems = submenu.itemArray;
    for (NSMenuItem *subsubitem in subsubitems) {
        GCLog(@"subsubitem == %@", subsubitem.title);
    }
}
// 指定菜单中的项目数。
NSInteger numberOfItems = _cus_menu.numberOfItems;
GCLog(@"指定菜单中的项目数 == %@", @(numberOfItems))

// 定当前高亮的菜单项
NSMenuItem *highlightedItem = _cus_menu.highlightedItem;
GCLog(@"定当前高亮的菜单项 == %@", highlightedItem.title)
// 指定菜单栏的高度。
CGFloat menuBarHeight = _cus_menu.menuBarHeight;
GCLog(@"指定菜单栏的高度 == %@", @(menuBarHeight))
// 指定菜单的尺寸
NSSize size = _cus_menu.size;
GCLog(@"指定菜单的尺寸 == %@", @(size))

// 返回指定索引位置的菜单项。
menu_item = [_cus_menu itemAtIndex:2];
GCLog(@"index == %@", menu_item)
// 返回指定标题的菜单项在菜单中的索引位置。
NSInteger index = [_cus_menu indexOfItem:menu_item];
// 返回指定标题的菜单项在菜单中的索引位置。
index = [_cus_menu indexOfItemWithTitle:@"123456"];
GCLog(@"index == %@", @(index))
// 返回指定标签的菜单项在菜单中的索引位置。
index = [_cus_menu indexOfItemWithTag:2];
GCLog(@"index == %@", @(index))
// 返回指定表示对象的菜单项在菜单中的索引位置。
index = [_cus_menu indexOfItemWithRepresentedObject:@"123456"];
GCLog(@"index == %@", @(index))
// 返回具有指定子菜单的菜单项在菜单中的索引位置。
index = [_cus_menu indexOfItemWithSubmenu:menu_item.submenu];
GCLog(@"index == %@", @(index))
// 返回具有指定目标和操作选择器的菜单项在菜单中的索引位置
index = [_cus_menu indexOfItemWithTarget:self andAction:@selector(menu_Tap)];
GCLog(@"index == %@", @(index))
// 返回具有指定标题的菜单项
menu_item = [_cus_menu itemWithTitle:@"234567"];
GCLog(@"menu_item == %@", menu_item)
// 返回具有指定标签的菜单项
menu_item = [_cus_menu itemWithTag:2];
GCLog(@"menu_item == %@", menu_item)
  • 1.4 代理

// 设置代理
_cus_menu.delegate = self;

#pragma mark - NSMenuDelegate
// 当一个菜单即将被显示时,该方法会被调用,用于更新菜单中的项目。
- (void)menuNeedsUpdate:(NSMenu *)menu {
    
}

// 返回菜单中的项数。
- (NSInteger)numberOfItemsInMenu:(NSMenu *)menu {
    if (menu == self.file_menu) {
        return 1;
    }
    else if (menu == self.edit_menu) {
        return 2;
    }
    else if (menu == self.view_menu) {
        return 3;
    }
    return 0;
}

// 用于在菜单显示之前更新菜单项的状态,比如是否可用、标题等
// 举例来说,假设我们有一个应用程序,在菜单中有一个“保存”选项。
// 但是,如果当前没有打开的文档,这个选项应该是禁用的。我们可以实现这个方法来更新这个菜单项的状态:
- (BOOL)menu:(NSMenu *)menu updateItem:(NSMenuItem *)item atIndex:(NSInteger)index shouldCancel:(BOOL)shouldCancel {
    // 假设保存菜单项的tag是1000
    if (item.tag == 1000) {
        // 判断是否有打开的文档
        if ([self hasOpenDocument]) {
            // 如果有文档,启用菜单项
            [item setEnabled:YES];
        }
        else {
            // 如果没有文档,禁用菜单项
            [item setEnabled:NO];
        }
    }
    return YES;
}

// 检查菜单是否有与给定事件匹配的键盘快捷键。
// 如果有,则返回YES,并将目标和操作设置为与该快捷键匹配的菜单项的目标和操作。
- (BOOL)menuHasKeyEquivalent:(NSMenu *)menu forEvent:(NSEvent *)event
                      target:(_Nullable id* _Nonnull)target
                      action:(_Nullable SEL* _Nonnull)action {
    
    return YES;
}

// 当菜单将要打开时调用。
- (void)menuWillOpen:(NSMenu *)menu {
    
}

// 当菜单关闭时调用。
- (void)menuDidClose:(NSMenu *)menu {
    
}

// 当菜单项将要高亮显示时调用。
- (void)menu:(NSMenu *)menu willHighlightItem:(nullable NSMenuItem *)item {
    
}

// 用于返回一个矩形框,该矩形框限制了菜单在屏幕上显示的范围。
// 该方法可以用于防止菜单显示在屏幕边缘之外或者显示在其他应用程序的窗口之上。
- (NSRect)confinementRectForMenu:(NSMenu *)menu onScreen:(nullable NSScreen *)screen {
    // 返回一个矩形框,该矩形框的左上角坐标是屏幕的左上角加上(10,10),宽度是屏幕宽度减去20,
    // 高度是屏幕高度减去20再减去菜单的高度。这样,菜单就只能在这个矩形框内显示,而不能超出这个范围。
    NSRect screenRect = [screen visibleFrame];
    NSSize size = [menu size];
    NSRect confinementRect = NSMakeRect(screenRect.origin.x + 10, screenRect.origin.y + 10, screenRect.size.width - 20, size.height - 20 - size.height);
    return confinementRect;
}
  • 1.5 其他调用

// 用来显示上下文菜单的
// 在指定的视图上显示指定的菜单,并且会在指定的事件位置弹出菜单。如果事件位置为nil,则菜单将在视图的中心位置弹出。
// + (void)popUpContextMenu:(NSMenu *)menu withEvent:(NSEvent*)event forView:(NSView*)view;
// 在指定的视图上显示指定的菜单,允许指定菜单中使用的字体。如果字体为nil,则使用系统默认字体。
// + (void)popUpContextMenu:(NSMenu *)menu withEvent:(NSEvent*)event forView:(NSView*)view withFont:(nullable NSFont *)font;
// 该方法用于更新菜单项的状态或内容,例如禁用或启用某个菜单项、更改菜单项的标题等。
[_cus_menu update];

// 该方法用于执行与键盘快捷键相关的菜单操作,例如按下“Command+C”执行复制操作。
// - (BOOL)performKeyEquivalent:(NSEvent *)event;
// 该方法在菜单项的状态或内容发生变化时被调用,可以用于更新菜单项的显示状态。
[_cus_menu itemChanged:menu_item];
// 该方法用于执行指定菜单项的操作,可以通过指定菜单项的索引来执行对应的操作。
[_cus_menu performActionForItemAtIndex:2];

// 该方法用于取消菜单的显示并且不执行任何操作。
[_cus_menu cancelTracking];
// 该方法与cancelTracking相似,但不会有菜单关闭的动画效果。
[_cus_menu cancelTrackingWithoutAnimation];
  • 1.6 效果样式

2、其他