响应rightMouse事件,我想调用一个显示上下文菜单的函数,运行它,并响应所选的菜单项。在Windows中,我可以将TrackPopupMenu与TPM_RETURNCMD标志一起使用。
在Cocoa中实现这个的最简单方法是什么?似乎NSMenu:popUpContextMenu想要将事件发布到指定的NSView。我必须创建一个虚拟视图并在返回之前等待事件吗?如果是这样,我如何“等待”或冲洗事件,因为我没有回到我的主?
答案 0 :(得分:2)
在Cocoa中执行此操作的“正确”方法是让菜单项的目标和操作执行所需的方法。但是,如果您必须在初始调用中执行此操作,则可以使用[NSView nextEventMatchingMask:]
不断获取您感兴趣的新事件,处理它们并循环。这是一个等待直到释放鼠标右键的示例。您可能希望使用更复杂的掩码参数,并不断调用[NSView nextEventMatchingMask:]
直到获得所需内容。
NSEvent *localEvent = [[self window] nextEventMatchingMask: NSRightMouseUpMask];
我认为你会找到更加轻松的“正确”方式。
答案 1 :(得分:1)
popUpContextMenu似乎已经是同步的。由于我没有看到使用NSMenu的方法而没有向NSView发送通知我想出了一个实例化临时NSView的方案。目标是显示一个弹出菜单,并在单个函数调用的上下文中返回所选项。以下是我提出的解决方案的代码片段:
// Dummy View class used to receive Menu Events
@interface DVFBaseView : NSView
{
NSMenuItem* nsMenuItem;
}
- (void) OnMenuSelection:(id)sender;
- (NSMenuItem*)MenuItem;
@end
@implementation DVFBaseView
- (NSMenuItem*)MenuItem
{
return nsMenuItem;
}
- (void)OnMenuSelection:(id)sender
{
nsMenuItem = sender;
}
@end
// Calling Code (in response to rightMouseDown event in my main NSView
void HandleRButtonDown (NSPoint pt)
{
NSRect graphicsRect; // contains an origin, width, height
graphicsRect = NSMakeRect(200, 200, 50, 100);
//-----------------------------
// Create Menu and Dummy View
//-----------------------------
nsMenu = [[[NSMenu alloc] initWithTitle:@"Contextual Menu"] autorelease];
nsView = [[[DVFBaseView alloc] initWithFrame:graphicsRect] autorelease];
NSMenuItem* item = [nsMenu addItemWithTitle:@"Menu Item# 1" action:@selector(OnMenuSelection:) keyEquivalent:@""];
[item setTag:ID_FIRST];
item = [nsMenu addItemWithTitle:@"Menu Item #2" action:@selector(OnMenuSelection:) keyEquivalent:@""];
[item setTag:ID_SECOND];
//---------------------------------------------------------------------------------------------
// Providing a valid windowNumber is key in getting the Menu to display in the proper location
//---------------------------------------------------------------------------------------------
int windowNumber = [(NSWindow*)myWindow windowNumber];
NSRect frame = [(NSWindow*)myWindow frame];
NSPoint wp = {pt.x, frame.size.height - pt.y}; // Origin in lower left
NSEvent* event = [NSEvent otherEventWithType:NSApplicationDefined
location:wp
modifierFlags:NSApplicationDefined
timestamp: (NSTimeInterval) 0
windowNumber: windowNumber
context: [NSGraphicsContext currentContext]
subtype:0
data1: 0
data2: 0];
[NSMenu popUpContextMenu:nsMenu withEvent:event forView:nsView];
NSMenuItem* MenuItem = [nsView MenuItem];
switch ([MenuItem tag])
{
case ID_FIRST: HandleFirstCommand(); break;
case ID_SECOND: HandleSecondCommand(); break;
}
}
答案 2 :(得分:0)
除了Carbon之外,没有直接的等价物,不推荐使用。
要检测右键单击,请按these instructions。它们可确保您正确检测右键和右键并在应有时显示菜单,而不应在不应显示时显示。
对于以下活动,您可以尝试[[NSRunLoop currentRunLoop] runMode:NSEventTrackingRunLoopMode untilDate:[NSDate distantFuture]]
。您需要反复调用,直到用户选择了其中一个菜单项。
使用nextEventMatchingMask:NSRightMouseUpMask
不适用于所有情况,甚至大多数情况。如果用户右键 - 在控件上单击,鼠标右键会在关闭后立即上升,而不会选择菜单项,菜单项选择可能(但不一定)通过鼠标左键。最好只重复运行循环,直到用户选择某个内容或取消菜单。
我不知道如何判断用户在没有选择任何内容的情况下解除了菜单。