2008-10-22 38 views
0

爲了響應rightMouse事件,我想調用一個顯示上下文菜單,運行它並響應所選菜單項的函數。在Windows中,我可以使用TrackPopupMenu和TPM_RETURNCMD標誌。Windows中的同步TrackPopupMenu在Cocoa中是否存在等效技術?

在Cocoa中實現這個最簡單的方法是什麼?看來NSMenu:popUpContextMenu想要將事件發佈到指定的NSView。我必須創建一個虛擬視圖並在返回之前等待事件嗎?如果是這樣,我如何「等待」或沖洗事件,因爲我不回到我的主要?

回答

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

在Cocoa中這樣做的「正確」方法是讓你的菜單項的目標和動作執行所需的方法。但是,如果您必須在首次調用中執行此操作,則可以使用[NSView nextEventMatchingMask:]繼續獲取您感興趣的新事件,處理它們並循環。這是一個等待直到釋放鼠標右鍵的例子。您可能需要使用更復雜的掩碼參數,並不斷調用[NSView nextEventMatchingMask:],直到獲得所需內容。

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

我想你會發現「適當」的路要走容易得多。

+0

謝謝本。我意識到「正確」的方式,但不想重新構建一些跨平臺的代碼。隱藏實現的函數調用將很好地爲我服務。我會試一試你的建議。 – AlanKley 2008-10-23 01:50:18

0

除碳以外,沒有直接的等價物,不贊成使用。

要檢測右鍵單擊,請按照these instructions。它們確保您可以正確檢測右鍵單擊和右鍵並在應該顯示菜單時顯示,而不顯示時不顯示。

對於以下事件,您可以嘗試[[NSRunLoop currentRunLoop] runMode:NSEventTrackingRunLoopMode untilDate:[NSDate distantFuture]]。您需要重複調​​用此選項,直到用戶選擇其中一個菜單項。使用nextEventMatchingMask:NSRightMouseUpMask將不適用於所有甚至大多數情況。如果用戶權限在您的控件上單擊了,則鼠標右鍵在其停止後會立即上升,而不會選擇菜單項,並且菜單項選擇可能(不一定)通過鼠標左鍵發生。最好只是反覆運行循環,直到用戶選擇某件東西或解散菜單爲止。

我不知道如何判斷用戶已經解散了菜單而沒有選擇任何東西。

相關問題