1

基本上我想创建系统菜单栏中提供的效果。用户按下菜单标题之一,当他在不同的标题上移动时,菜单会自动打开。

问题是,如果我打开一个按钮的弹出菜单,用户必须再次单击才能关闭它。整个运行循环处于暂停状态,因为我相信弹出菜单是模态的。当用户移动到下一个按钮时,如何才能发送 [somePopUpMenu cancelTracking]?

这是我目前在我的 NSWindow 子类中尝试的代码。关键是一旦鼠标退出一个按钮,鼠标在下一个按钮上自动点击(leftdown/leftup),定时器失效,弹出菜单取消。

假设弹出菜单打开并且鼠标存在,则触发 leftdown/leftup 事件(我知道这有效,因为我将它们记录在 NSLog 的 mouseDown 和 mouseUp 中),计时器无效,但弹出菜单仍在显示,并且假事件“点击”的另一个按钮不显示任何内容。此外,整个事情进入一个循环,并且由于某种原因发送了疯狂的 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从 Mac OS X 10.5开始响应cancelTracking消息。

于 2010-03-24T13:57:33.530 回答