0

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

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

4

3 回答 3

2

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

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

我认为您会找到更容易的“正确”方法。

于 2008-10-23T00:00:06.463 回答
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;
    }
 }
于 2008-10-23T18:15:45.690 回答
0

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

要检测右键单击,请按照这些说明进行操作。它们确保您能够正确检测右键单击和按住不放,并在应该显示菜单时显示菜单,在不应该显示时不显示菜单。

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

使用nextEventMatchingMask:NSRightMouseUpMask不会在所有情况下,甚至在大多数情况下都有效。如果用户在您的控件上单击鼠标右键,鼠标右键会在它下降后立即上升,而无需选择菜单项,并且菜单项选择可能(尽管不一定)通过鼠标左键发生。最好重复运行运行循环,直到用户选择某些内容或关闭菜单。

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

于 2008-10-23T03:52:20.957 回答