响应rightMouse事件,我想调用一个显示上下文菜单的函数,运行它,并响应所选的菜单项。在Windows中,我可以将TrackPopupMenu与TPM_RETURNCMD标志一起使用。

在Cocoa中实现这个的最简单方法是什么?似乎NSMenu:popUpContextMenu想要将事件发布到指定的NSView。我必须创建一个虚拟视图并在返回之前等待事件吗?如果是这样,我该如何“等待”给我冲洗的事件我没有回到我的主?

有帮助吗?

解决方案 2

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;
    }
 }

其他提示

在Cocoa中执行此操作的“正确”方法是让菜单项的目标和操作执行所需的方法。但是,如果必须在初始调用中执行此操作,则可以使用 [NSView nextEventMatchingMask:] 来持续获取您感兴趣,处理它们并循环的新事件。这是一个等待直到释放鼠标右键的示例。您可能希望使用更复杂的掩码参数,并不断调用 [NSView nextEventMatchingMask:] ,直到获得所需内容。

<代码>

NSEvent *localEvent = [[self window] nextEventMatchingMask: NSRightMouseUpMask];

我认为你会找到更加轻松的“正确”方式。

除了Carbon之外,没有直接的等价物,不推荐使用。

要检测右键单击,请按照这些说明。它们可确保您正确检测右键和右键并在应有时显示菜单,而不应在不应显示时显示。

对于以下事件,您可以尝试 [[NSRunLoop currentRunLoop] runMode:NSEventTrackingRunLoopMode untilDate:[NSDate distantFuture]] 。您需要反复调用,直到用户选择了其中一个菜单项。

使用 nextEventMatchingMask:NSRightMouseUpMask 将不适用于所有情况,甚至大多数情况。如果用户右键 - 在控件上单击,鼠标右键会在关闭后立即上升,而不会选择菜单项,菜单项选择可能(但不一定)通过鼠标左键。最好只重复运行循环,直到用户选择某个内容或取消菜单。

我不知道如何判断用户在没有选择任何内容的情况下解除了菜单。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top