По сути, я хочу создать эффект, представленный в строке меню системы. Пользователь нажимает на один из заголовков меню, и когда он перемещается по различным заголовкам, меню открываются автоматически.
Загвоздка в том, что если я открываю всплывающее меню для кнопки, пользователь должен нажать еще раз, чтобы закрыть ее. Весь цикл запуска приостановлен, так как я считаю, что всплывающее меню является модальным. Как я могу отправлять [somePopUpMenu cancelTracking], когда пользователь переходит к следующей кнопке?
Вот код, который я сейчас пробую в своем подклассе NSWindow. Дело в том, что как только мышь выходит из кнопки, мышь автоматически нажимается (влево / вниз) на следующей кнопке, таймер становится недействительным и всплывающее меню отменяется.
Предполагая, что всплывающее меню открыто и мышь существует, события 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];
}