2011-08-30 22 views
5

Pracuję nad aplikacją dla OS X, w której używam niestandardowego okna, które rysuje obraz jako tło, w tym pasek tytułu. Modyfikuję this code, aby narysować okno, a następnie wywołanie [NSWindow standardWindowButton: forStyleMask:], aby uzyskać standardowe przyciski zamykania, minimalizowania i maksymalizowania.Nadpisanie przycisku zamknięcia NSWindow

Problem polega na tym, że moja aplikacja korzysta z NSPopover, a kiedy zamykam lub minimalizuję aplikację, gdy popover jest otwarty, zamknie okno popover lub wyświetli animację popover, minimalizującą zamiast zamykania aplikacji. Czy istnieje sposób na przesłonięcie domyślnego zamknięcia/zminimalizowania zachowania w NSWindow, aby najpierw odrzucić wszelkie otwarte pakiety?

Dziękuję i przepraszam, jeśli to oczywiste pytanie - po raz pierwszy pracuję z zestawem SDK OS X, więc nie mam dużego doświadczenia.

EDIT: Kilka godzin po tym, jak pisał to myślałem, że to oczywiste rozwiązanie - użyć NSWindowDelegate metod "windowWillClose:" A "windowWillMiniaturize:" i odrzucenie popovers tam. Jednak wydaje się, że ponieważ przyciski close/minimize zamykają popover, to jeśli popover jest otwarty, te metody delegatów nie będą wywoływane. To prowadzi mnie z powrotem do kroku 1, ale mam nadzieję, że poznanie tego zachowania pomoże komuś rozwiązać problem.

Jest również inny problem z NSPopovers i nie wiem, czy jest podłączony czy nie, więc pomyślałem, że dodam go tutaj, na wypadek gdyby była wspólna przyczyna. Czasami, gdy próbuję odrzucić popover, otrzymam ten błąd (dla kontekstu, naciskam przycisk NSButton, który wywołuje funkcję, która sprawdza istnienie popover, a jeśli istnieje, zamyka go):

2011-08-30 11:24:08.949 Playground[11194:707] *** Assertion failure in +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:], /SourceCache/AppKit/AppKit-1138/AppKit.subproj/NSView.m:11026 
2011-08-30 11:24:08.950 Playground[11194:707] this method is supposed to only be invoked on top level items 
2011-08-30 11:24:08.958 Playground[11194:707] (
    0 CoreFoundation      0x00007fff873d4986 __exceptionPreprocess + 198 
    1 libobjc.A.dylib      0x00007fff87ac6d5e objc_exception_throw + 43 
    2 CoreFoundation      0x00007fff873d47ba +[NSException raise:format:arguments:] + 106 
    3 Foundation       0x00007fff8950314f -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 169 
    4 AppKit        0x00007fff88211064 +[NSView _findFirstKeyViewInDirection:forKeyLoopGroupingView:] + 137 
    5 AppKit        0x00007fff87d1f546 _replacementKeyViewAlongKeyViewPath + 565 
    6 AppKit        0x00007fff87d1f2ff -[NSView nextValidKeyView] + 179 
    7 AppKit        0x00007fff87d1f199 -[NSWindow _selectFirstKeyView] + 714 
    8 AppKit        0x00007fff882361cf _NSWindowRecursiveFindFirstResponder + 164 
    9 AppKit        0x00007fff882395c8 _NSWindowExchange + 79 
    10 AppKit        0x00007fff883a7e3a -[_NSWindowTransformAnimation startAnimation] + 426 
    11 AppKit        0x00007fff87c98bb2 -[NSWindow _doOrderWindow:relativeTo:findKey:forCounter:force:isModal:] + 592 
    12 AppKit        0x00007fff87c9890f -[NSWindow orderWindow:relativeTo:] + 154 
    13 AppKit        0x00007fff883dfaf0 _NSPopoverCloseAndAnimate + 948 
    14 Playground       0x00000001000078a4 -[MainWindowController dismissPopover:] + 100 
    15 Playgorund       0x0000000100007012 -[MainWindowController requestWasClicked:] + 98 
    16 CoreFoundation      0x00007fff873c411d -[NSObject performSelector:withObject:] + 61 
    17 AppKit        0x00007fff87ca2852 -[NSApplication sendAction:to:from:] + 139 
    18 AppKit        0x00007fff87ca2784 -[NSControl sendAction:to:] + 88 
    19 AppKit        0x00007fff87ca26af -[NSCell _sendActionFrom:] + 137 
    20 AppKit        0x00007fff87ca1b7a -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 2014 
    21 AppKit        0x00007fff87d2157c -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 489 
    22 AppKit        0x00007fff87ca0786 -[NSControl mouseDown:] + 786 
    23 AppKit        0x00007fff87c6b66e -[NSWindow sendEvent:] + 6280 
    24 AppKit        0x00007fff87c03f19 -[NSApplication sendEvent:] + 5665 
    25 AppKit        0x00007fff87b9a42b -[NSApplication run] + 548 
    26 AppKit        0x00007fff87e1852a NSApplicationMain + 867 
    27 Playground       0x0000000100001c52 main + 34 
    28 Playground       0x0000000100001c24 start + 52 
    29 ???         0x0000000000000001 0x0 + 1 
) 

Odpowiedz

3

Rozwiązanie okazało się dość proste.

Kiedy utworzony przycisk na NSWindow, zmieniłem działania i cel przycisku:

[closeButton setTarget:self.delegate]; // alternatively you can make it self.windowController 
[closeButton setAction:@selector(closeThisWindow:)]; 

A potem w podklasie NSWindowController, I wdrożone metody:

-(void)closeThisWindow { 
    [self close]; // for the minimize button you'll call [self.window miniaturize] 
} 

Dla z jakiegoś powodu, aktualizacje NSP zawsze pojawiają się ponownie, gdy okno zostanie ponownie otwarte lub nieminimalnie; ponieważ faktycznie chcę tego zachowania w mojej aplikacji, to nie jest problem, ale należy o tym pamiętać, jeśli używasz tego rozwiązania. Jeśli nie masz żadnych okien podrzędnych, możesz po prostu powtórzyć numer self.window.childWindows, ponieważ przejmowania NSP są uważane za okna podrzędne. Jeśli masz inne okna podrzędne, które chcesz obsługiwać osobno, możesz dodać tablicę do podklasy NSWindow, która monitoruje wszystkie twoje popouvery i po prostu iteruje przez to.

+0

Ale ... co ze śladami stosu ?! MUSZĘ WIEDZIEĆ. –

+0

@ Big-OClaire Niestety, to pytanie ma już prawie 6 lat i nie mam już dostępu do kodu źródłowego, więc nie mogę ci pomóc. Przepraszam! – Aaron