0

rightMouse イベントに応答して、コンテキスト メニューを表示し、それを実行して、選択されたメニュー項目に応答する関数を呼び出したいと考えています。Windows では、TPM_RETURNCMD フラグを指定して TrackPopupMenu を使用できます。

これをCocoaで実装する最も簡単な方法は何ですか? NSMenu:popUpContextMenu は、指定された NSView にイベントを投稿したいようです。ダミー ビューを作成し、イベントを待ってから戻る必要がありますか? もしそうなら、メインに戻っていない場合、どうすればイベントを「待機」またはフラッシュできますか?

4

3 に答える 3

2

Cocoa でこれを行う「適切な」方法は、メニュー項目のターゲットとアクションに必要なメソッドを実行させることです。ただし、最初の呼び出しでそれを行う必要がある場合は、 を使用[NSView nextEventMatchingMask:]して、興味のある新しいイベントを継続的にフェッチし、それらを処理して、ループすることができます。マウスの右ボタンが離されるまで待機する例を次に示します。おそらく、より複雑なマスク引数を使用して、必要な[NSView nextEventMatchingMask:]ものが得られるまで継続的に呼び出したいと思うでしょう。

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

「適切な」方法がずっと簡単に見つかると思います。

于 2008-10-23T00:00:06.463 に答える
1

popUpContextMenuはすでに同期しているようです。NSViewに通知を送信せずにNSMenuを使用する方法がわからなかったため、一時的な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]]。ユーザーがメニュー項目の 1 つを選択するまで、これを繰り返し呼び出す必要があります。

を使用nextEventMatchingMask:NSRightMouseUpMaskすると、すべての場合、またはほとんどの場合でさえ機能しません。ユーザーがコントロールを右クリックすると、メニュー項目を選択せず​​に、マウスの右ボタンが下がった直後に上に移動し、メニュー項目の選択はおそらく (必ずというわけではありませんが) 左マウス ボタンを介して行われます。ユーザーが何かを選択するか、メニューを閉じるまで、実行ループを繰り返し実行することをお勧めします。

ユーザーが何も選択せずにメニューを閉じたことを伝える方法がわかりません。

于 2008-10-23T03:52:20.957 に答える