Custom NSView in NSMenuItem not receiving mouse events

二次信任 提交于 2019-12-09 04:46:40

问题


I have an NSMenu popping out of an NSStatusItem using popUpStatusItemMenu. These NSMenuItems show a bunch of different links, and each one is connected with setAction: to the openLink: method of a target. This arrangement has been working fine for a long time. The user chooses a link from the menu and the openLink: method then deals with it.

Unfortunately, I recently decided to experiment with using NSMenuItem's setView: method to provide a nicer/slicker interface. Basically, I just stopped setting the title, created the NSMenuItem, and then used setView: to display a custom view. This works perfectly, the menu items look great and my custom view is displayed.

However, when the user chooses a menu item and releases the mouse, the action no longer works (i.e., openLink: isn't called). If I just simply comment out the setView: call, then the actions work again (of course, the menu items are blank, but the action is executed properly). My first question, then, is why setting a view breaks the NSMenuItem's action.

No problem, I thought, I'll fix it by detecting the mouseUp event in my custom view and calling my action method from there. I added this method to my custom view:

- (void)mouseUp:(NSEvent *)theEvent {
  NSLog(@"in mouseUp");
  }

No dice! This method is never called.

I can set tracking rects and receive mouseEntered: events, though. I put a few tests in my mouseEntered routine, as follows:

if ([[self window] ignoresMouseEvents]) {  NSLog(@"ignoring mouse events");  }
else {  NSLog(@"not ignoring mouse events");  }
if ([[self window] canBecomeKeyWindow]) {  dNSLog((@"canBecomeKeyWindow"));  }
else {  NSLog(@"not canBecomeKeyWindow");  }
if ([[self window] isKeyWindow]) {  dNSLog((@"isKeyWindow"));  }
else {  NSLog(@"not isKeyWindow");  }

And got the following responses:

not ignoring mouse events
canBecomeKeyWindow
not isKeyWindow

Is this the problem? "not isKeyWindow"? Presumably this isn't good because Apple's docs say "If the user clicks a view that isn’t in the key window, by default the window is brought forward and made key, but the mouse event is not dispatched." But there must be a way do detect these events. HOW?

Adding:

[[self window] makeKeyWindow];

has no effect, despite the fact that canBecomeKeyWindow is YES.


回答1:


Add this method to your custom NSView and it will work fine with mouse events

- (void)mouseUp:(NSEvent*) event {
    NSMenuItem* mitem = [self enclosingMenuItem];
    NSMenu* m = [mitem menu];
    [m cancelTracking];
    [m performActionForItemAtIndex: [m indexOfItem: mitem]];
}

But i'm having problems with keyhandling, if you solved this problem maybe you can go to my question and help me a little bit.




回答2:


Add this to your custom view and you should be fine:

- (BOOL)acceptsFirstMouse:(NSEvent *)theEvent
{
    return YES;
}



回答3:


I added this method to my custom view, and now everything works beautifully:

- (void)viewDidMoveToWindow {
    [[self window] becomeKeyWindow];
}

Hope this helps!




回答4:


So far, the only way to achieve the goal, is to register a tracking area manually in updateTrackingAreas - that is thankfully called, like this:

override func updateTrackingAreas() {
    let trackingArea = NSTrackingArea(rect: bounds, options: [.enabledDuringMouseDrag, .mouseEnteredAndExited, .activeInActiveApp], owner: self, userInfo: nil)
    addTrackingArea(trackingArea)
}



回答5:


Recently I needed to show a Custom view for a NSStatusItem, show a regular NSMenu when clicking on it and supporting drag and drop operations on the Status icon.

I solved my problem using, mainly, three different sources that can be found in this question.

Hope it helps other people.




回答6:


See the sample code from Apple named CustomMenus In there you'll find a good example in the ImagePickerMenuItemView class.

It's not simple or trivial to make a view in a menu act like a normal NSMenuItem. There are some real decisions and coding to do.



来源:https://stackoverflow.com/questions/1395556/custom-nsview-in-nsmenuitem-not-receiving-mouse-events

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!