美文网首页码农的世界Mac OS XMac OS X 软件开发
一步一步熟悉Mac app开发(五)之Menu Bar和Popo

一步一步熟悉Mac app开发(五)之Menu Bar和Popo

作者: 拳战攻城师 | 来源:发表于2018-07-31 22:43 被阅读31次

    概要

    本文共分为个阶段,每个阶段完成后都可以看到阶段性成果。
    阶段一、显示Menu Bar小图标。
    阶段二、隐藏程序窗口和启动栏图标。(无图)
    阶段三、点击MenuBar小图标,出现菜单。
    阶段四、点击MenuBar小图标,出现一个小窗口。
    阶段五、通过事件监听鼠标点击,“智能”关闭小窗口。

    阶段一

    1.创建工程,向工程中加入图标,对图标资源进行设置。


    图标在此 image.png image.png

    2.在AppDelegate.h中添加NSStatusItem类型的指针变量,对其进行初始化操作,定义一个getDiamond函数。

    //AppDelegate.m
    #import "AppDelegate.h"
    
    @interface AppDelegate ()
    
    @property NSStatusItem *statusItem;
    - (void) getDiamond:(NSStatusBarButton *)sender;
    
    @end
    
    @implementation AppDelegate
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        // Insert code here to initialize your application
        
        //初始化_statusItem
        _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
        
        //设置_statusItem按钮相关信息
        NSStatusBarButton *button = _statusItem.button;
        if(button){
            button.image = [NSImage imageNamed:@"zuan"];
            button.action = @selector(getDiamond:);
        }
    }
    
    - (void) getDiamond:(NSStatusBarButton *)sender {
        NSLog(@"You get a lot of diamonds!");
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
        // Insert code here to tear down your application
    }
    @end
    
    

    3.Command+R运行,效果如下。


    image.png

    阶段二

    1.打开storyboard,选中窗口,取消勾选【Is initial Controller】便可去掉窗口。


    image.png

    2.打开工程设置,点击【Info】,新增“Application is agent (UIElement)”选项,其值为YES。


    image.png

    3.阶段二完成!

    阶段三

    1.注释掉AppDelegate.m中applicationDidFinishLaunching函数内部的如下语句

    //button.action = @selector(getDiamond:);
    

    2.在applicationDidFinishLaunching函数中添加如下语句。

        NSMenu *menu;
        menu = [[NSMenu alloc] init];
        [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Get Diamond" action:@selector(getDiamond:) keyEquivalent:@"g"] ];
        [menu addItem:[NSMenuItem separatorItem]];
        [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"] ];
        _statusItem.menu = menu;
    

    3.AppDelegate.m修改后的完整版代码如下。

    #import "AppDelegate.h"
    @interface AppDelegate ()
    @property NSStatusItem *statusItem;
    - (void) getDiamond:(NSStatusBarButton *)sender;
    @end
    
    @implementation AppDelegate
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        // Insert code here to initialize your application
        
        //初始化_statusItem
        _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
        
        //设置_statusItem按钮相关信息
        NSStatusBarButton *button = _statusItem.button;
        if(button){
            button.image = [NSImage imageNamed:@"zuan"];
            //button.action = @selector(getDiamond:);
        }
        
        NSMenu *menu;
        menu = [[NSMenu alloc] init];
        [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Get Diamond" action:@selector(getDiamond:) keyEquivalent:@"g"] ];
        [menu addItem:[NSMenuItem separatorItem]];
        [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"] ];
        _statusItem.menu = menu;
    }
    
    - (void) getDiamond:(NSStatusBarButton *)sender {
        NSLog(@"You get a lot of diamonds!");
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
        // Insert code here to tear down your application
    }
    @end
    

    4.阶段三完成,效果如下。


    image.png

    阶段四

    1.添加一个ViewController的子类GetDiamonds,创建xib文件,声明并完成其初始化方法。

    //DiamondViewController.h
    #import <Cocoa/Cocoa.h>
    @interface DiamondViewController : NSViewController
    - (id) initWithCustom;
    @end
    
    //DiamondViewController.m
    - (id) initWithCustom{
        self = [super initWithNibName:@"DiamondViewController" bundle:nil];
        return self;
    }
    

    2.点击DiamondViewController.xib文件,选择label拖拽直View中央。


    image.png

    3.打开AppDelegate.m,新增一个NSPopver的指针变量,新增部分代码,完成后代码如下。

    #import "AppDelegate.h"
    #import "DiamondViewController.h"
    @interface AppDelegate ()
    
    @property NSStatusItem *statusItem;
    @property NSPopover *popover;
    - (void) getDiamond:(NSStatusBarButton *)sender;
    - (void)toggleWeather:(NSStatusBarButton *)sender
    @end
    
    @implementation AppDelegate
    
    - (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
        // Insert code here to initialize your application
        
        //初始化_statusItem
        _statusItem = [[NSStatusBar systemStatusBar] statusItemWithLength:NSVariableStatusItemLength];
        
        //设置_statusItem按钮相关信息
        NSStatusBarButton *button = _statusItem.button;
        if(button){
            button.image = [NSImage imageNamed:@"zuan"];
            //修改
            button.action = @selector(toggleDiamond:);
        }
    // 将menu注释掉。
    //    NSMenu *menu;
    //    menu = [[NSMenu alloc] init];
    //    [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Get Diamond" action:@selector(getDiamond:) keyEquivalent:@"g"] ];
    //    [menu addItem:[NSMenuItem separatorItem]];
    //    [menu addItem:[[NSMenuItem alloc] initWithTitle:@"Quit" action:@selector(terminate:) keyEquivalent:@"q"] ];
    //    _statusItem.menu = menu;
      
        //新增
        _popover = [[NSPopover alloc] init];
        _popover.contentViewController = [[DiamondViewController alloc] initWithCustom];
    }
    
    - (void) getDiamond:(NSStatusBarButton *)sender {
        NSLog(@"You get a lot of diamonds!");
    }
    
    //新增
    - (void)toggleDiamond:(NSStatusBarButton *)sender{
        if([_popover isShown]){
            [_popover performClose:sender];
        }else{
            NSStatusBarButton *button = _statusItem.button;
            if(button){
                [_popover showRelativeToRect:button.bounds ofView:button preferredEdge:NSRectEdgeMinY];
            }
        }
    }
    
    - (void)applicationWillTerminate:(NSNotification *)aNotification {
        // Insert code here to tear down your application
    }
    @end
    
    

    4.阶段四完成,效果如下。


    image.png

    阶段五

    1.新建NSObject的子类EventMonitor,代码如下。

    //EventMonitor.h
    import <Cocoa/Cocoa.h>
    @interface EventMonitor : NSObject
    @property id monitor;
    @property NSEventMask mask;
    @property void (^handler)(NSEvent *);
    - (id) initWithMaskAndHandler:(NSEventMask)mask handler:(void (^)(NSEvent *))handler;
    - (void) start;
    - (void) stop;
    @end
    
    //EventMonitor.m
    #import "EventMonitor.h"
    @implementation EventMonitor
    - (id) initWithMaskAndHandler:(NSEventMask)mask handler:(void (^)(NSEvent *)) handler {
        self = [super init];
        if(self){
            _mask = mask;
            _handler = handler;
        }
        return self;
    }
    
    - (void) start{
        _monitor = [NSEvent addGlobalMonitorForEventsMatchingMask:_mask handler:_handler];
    }
    
    - (void) stop{
        if(_monitor != nil ){
            [NSEvent removeMonitor:_monitor];
            _monitor = nil;
        }
    }
    @end
    

    3.打开AppDelegate.m,添加EventMonitor的成员变量,并对其进行初始化。

    @property EventMonitor* eventMonitor;
     _eventMonitor = [[EventMonitor alloc] initWithMaskAndHandler:NSEventMaskLeftMouseUp|NSEventMaskRightMouseUp handler:^(NSEvent *h) {
            if([_popover isShown]){
                [self closePopover:h];
            }
        }];
    

    4.对代码进行修改,新增closePopover和showPopover函数,修改toggleDiamond函数部分代码。

    //新增
    -(void) closePopover:(id)sender{
        [_popover performClose:sender];
        
        [_eventMonitor stop];
    }
    
    //新增
    -(void) showPopover:(id)sender{
        NSStatusBarButton *button = [_statusItem button];
        if(button){
            [_popover showRelativeToRect:button.bounds ofView:button preferredEdge:NSRectEdgeMinY];
        }
        [_eventMonitor start];
    }
    
    -(void) toggleDiamond:(NSStatusBarButton *)sender{
        if([_popover isShown]){
            //修改
            [self closePopover:sender];
        }else{
            //修改
            [self showPopover:sender];
        }
    }
    

    5.阶段五完成,效果如下。


    image.png

    结语

    想了解更多关于Popover的用法,详见:一步一步熟悉Mac app开发(九)之NSPopover

    相关文章

      网友评论

        本文标题:一步一步熟悉Mac app开发(五)之Menu Bar和Popo

        本文链接:https://www.haomeiwen.com/subject/weycvftx.html