1

基本的に、システムのメニュー バーで提供される効果を作成したいと考えています。ユーザーがメニューの見出しの 1 つを押して、さまざまな見出しを移動すると、メニューが自動的に開きます。

問題は、ボタンのポップアップ メニューを開くと、ユーザーがもう一度クリックして閉じる必要があることです。ポップアップメニューがモーダルだと思うので、ランループ全体が保留中です。ユーザーが次のボタンに移動したときに [somePopUpMenu cancelTracking] を送信できるようにするにはどうすればよいですか?

NSWindow サブクラスで現在試しているコードは次のとおりです。ポイントは、マウスがボタンから出ると、次のボタンでマウスが自動的にクリック (左下/左上) され、タイマーが無効になり、ポップアップ メニューがキャンセルされることです。

ポップアップ メニューが開いていて、マウスが存在すると仮定すると、leftdown/leftup イベントが発生し (これは、mouseDown と mouseUp の NSLog にログを記録するので、これが機能することがわかっています)、タイマーは無効になりますが、ポップアップ メニューは引き続き表示されます。偽のイベントによって「クリック」された他のボタンには何も表示されません。また、全体がループに陥り、何らかの理由で取り乱した mouseDown/mouseUp が送信されます。

hookToMenu には適切な参照がありますが、ポップアップ メニューが別のオブジェクトで作成されていることに注意してください (デバッグ/ステップ スルーで確認しました)。

イベント追跡タイマーを中断しているのか、間違った方法で実行しているのかはわかりません。ウィンドウコントローラーでも試してみましたが、同じ結果が得られました。

これに関する助けをいただければ幸いです。

-(void)stopTimer
{
    [timer invalidate];
    [hookToMenu cancelTracking]; //hookToMenu is NSMenu*
}

-startFireDateTimer
{
    NSDate *fireDate = [NSDate dateWithTimeIntervalSinceNow:0];
    timer = [[NSTimer alloc] initWithFireDate:nil interval:0 target:self selector:@selector(targetMethod)      userInfo:nil  repeats:YES];

    NSRunLoop *runLoop = [NSRunLoop currentRunLoop];
    [runLoop addTimer:timer forMode:NSEventTrackingRunLoopMode];
    [timer release];
}

-(void)targetMethod
{
    NSEvent *newEvent;

    newEvent=[NSApp nextEventMatchingMask:NSMouseExitedMask untilDate:[NSDate distantFuture] inMode:NSEventTrackingRunLoopMode dequeue:NO];

    if ([newEvent type]==NSMouseExited)
    {
        NSPoint mouseLoc;

        mouseLoc=[newEvent locationInWindow];

        int type=NSLeftMouseDown;
        int type2=NSLeftMouseUp;
        int windowNumber=[self windowNumber];

        id fakeMouseUpEvent=[NSEvent mouseEventWithType:type
                                               location:mouseLoc
                                          modifierFlags:nil 
                                              timestamp:[NSDate timeIntervalSinceReferenceDate]
                                           windowNumber:windowNumber 
                                                context:nil
                                            eventNumber:nil 
                                             clickCount:1 
                                               pressure:1];

        id fakeMouseUpEvent2=[NSEvent mouseEventWithType:type2
                                                location:mouseLoc
                                           modifierFlags:nil 
                                               timestamp:[NSDate timeIntervalSinceReferenceDate]
                                            windowNumber:windowNumber 
                                                 context:nil
                                             eventNumber:nil 
                                              clickCount:1 
                                                pressure:1];

        [NSApp sendEvent:fakeMouseUpEvent];
        [NSApp sendEvent:fakeMouseUpEvent2];

        [self stopTimer];
    }
}

-(void)mouseDown:(NSEvent *)theEvent
{    
    [self startFireDateTimer];

    NSLog(@"WINDOW: mouse down in window!");

    [super mouseDown:theEvent];
}

-(void)mouseUp:(NSEvent *)theEvent
{    
    NSLog(@"WINDOW: mouse up in window!");

    [super mouseUp:theEvent];
}
4

1 に答える 1

0

ユーザーが次のボタンに移動したときに [somePopUpMenu cancelTracking] を送信できるようにするにはどうすればよいですか?

まさにそれをしてください。NSMenu はcancelTracking、Mac OS X 10.5 以降のメッセージに応答します。

于 2010-03-24T13:57:33.530 に答える