基本上我想创建系统菜单栏中提供的效果。用户按下菜单标题之一,当他在不同的标题上移动时,菜单会自动打开。
问题是,如果我打开一个按钮的弹出菜单,用户必须再次单击才能关闭它。整个运行循环处于暂停状态,因为我相信弹出菜单是模态的。当用户移动到下一个按钮时,如何才能发送 [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];
}