我想在应用程序的主菜单中添加一个菜单项,这将很少使用.我希望默认情况下隐藏它并仅在用户按住Option键时显示它.我该怎么做呢?
看来我应该处理flagsChanged:
,但这是NSResponder
方法而NSMenu
不是继承NSResponder
?我在主窗口控制器中尝试了它,当我点击菜单之前按下Option键时它可以正常工作.以下用例不起作用:单击菜单项(没有项目),按选项键 - 我的项目应该出现,释放选项键 - 项目应该消失.
我也试着NSEvent的addLocalMonitorForEventsMatchingMask:handler:
和addGlobalMonitorForEventsMatchingMask:handler:
用于NSFlagsChangedMask
但是当同时打开主菜单无论本地或全局处理程序不会触发选项键按下.
我怎样才能做到这一点?
Mat*_*ens 11
构建菜单时包含可选项并将其标记为隐藏.然后将类实例设置为菜单的委托,并在菜单打开时添加运行循环观察器以控制可选项的隐藏状态.
@implementation AppController {
CFRunLoopObserverRef _menuObserver;
}
- (void)updateMenu {
BOOL hideOptionalMenuItems = ([NSEvent modifierFlags] & NSAlternateKeyMask) != NSAlternateKeyMask;
[self.optionalMenuItem setHidden:hideOptionalMenuItems];
}
- (void)menuWillOpen:(NSMenu *)menu {
[self updateMenu];
if (_menuObserver == NULL) {
_menuObserver = CFRunLoopObserverCreateWithHandler(NULL, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
[self updateMenu];
});
CFRunLoopAddObserver(CFRunLoopGetCurrent(), _menuObserver, kCFRunLoopCommonModes);
}
}
- (void)menuDidClose:(NSMenu *)menu {
if (_menuObserver != NULL) {
CFRunLoopObserverInvalidate(_menuObserver);
CFRelease(_menuObserver);
_menuObserver = NULL;
}
}
Run Code Online (Sandbox Code Playgroud)
小智 7
将以下内容添加到applicationDidFinishLaunching中.
// Dynamically update QCServer menu when option key is pressed
NSMenu *submenu = [[[NSApp mainMenu] itemWithTitle:@"QCServer"] submenu];
NSTimer *t = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(updateMenu:) userInfo:submenu repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:t forMode:NSEventTrackingRunLoopMode];
Run Code Online (Sandbox Code Playgroud)
然后加
- (void)updateMenu:(NSTimer *)t {
static NSMenuItem *menuItem = nil;
static BOOL isShowing = YES;
// Get global modifier key flag, [[NSApp currentEvent] modifierFlags] doesn't update while menus are down
CGEventRef event = CGEventCreate (NULL);
CGEventFlags flags = CGEventGetFlags (event);
BOOL optionKeyIsPressed = (flags & kCGEventFlagMaskAlternate) == kCGEventFlagMaskAlternate;
CFRelease(event);
NSMenu *menu = [t userInfo];
if (!menuItem) {
// View Batch Jobs...
menuItem = [menu itemAtIndex:6];
[menuItem retain];
}
if (!isShowing && optionKeyIsPressed) {
[menu insertItem:menuItem atIndex:6];
[menuItem setEnabled:YES];
isShowing = YES;
} else if (isShowing && !optionKeyIsPressed) {
[menu removeItem:menuItem];
isShowing = NO;
}
NSLog(@"optionKeyIsPressed %d", optionKeyIsPressed);
}
Run Code Online (Sandbox Code Playgroud)
计时器仅在跟踪控件时触发,因此不会影响性能.
归档时间: |
|
查看次数: |
4366 次 |
最近记录: |