2009-04-19 15 views
8

Tengo una aplicación Cocoa que muestra una alerta de aplicación modal utilizando la clase NSAlert. Me gustaría que la ventana de alerta flote sobre todas las ventanas de otras aplicaciones. ¿Se puede hacer esto con NSAlert, o tengo que implementar mi propia ventana?¿Se puede utilizar NSAlert para crear una ventana flotante?

No sé si algo de esto importa, pero la aplicación es una aplicación de agente (LSUIElement es verdad) implementada como NSStatusItem. (Para obtener más información sobre la aplicación, incluyendo el código fuente, busque <here>.)

Aquí está el código que muestra la alerta:

- (void)showTimerExpiredAlert { 
    [NSApp activateIgnoringOtherApps:YES]; 

    NSAlert *alert = [[NSAlert alloc] init]; 
    [alert setAlertStyle:NSInformationalAlertStyle]; 
    [alert setMessageText:NSLocalizedString(@"Menubar Countdown Complete", @"Expiration message")]; 
    [alert setInformativeText:NSLocalizedString(@"The countdown timer has reached 00:00:00.", 
               @"Expiration information")]; 
    [alert addButtonWithTitle:NSLocalizedString(@"OK", @"OK button title")]; 
    [alert addButtonWithTitle:NSLocalizedString(@"Restart Countdown...", @"Restart button title")]; 

    NSInteger clickedButton = [alert runModal]; 
    [alert release]; 

    if (clickedButton == NSAlertSecondButtonReturn) { 
     // ... 
    } 
} 

He intentado poner esto antes de la runModal llamada:

[[alert window] setFloatingPanel:YES]; 

también he intentado esto:

[[alert window] setLevel:NSFloatingWindowLevel]; 

Pero neit el de ella hace que la ventana se mantenga por encima de otras si hago clic en la ventana de otra aplicación. Sospecho que runModal simplemente no respeta ninguna de esas configuraciones.

+1

cada vez que se llama runModal, restablece el nivel de la ventana, no estoy seguro si eso ayuda ... – cobbal

Respuesta

5

Arruine mi cerebro sobre esta cosa exacta hace un tiempo.

La única forma en que podía hacer que esto funcionara (más o menos), era subclase NSApplication y anulación -sendEvent. En -sendEvent, que le llama por primera vez la aplicación de súper, y luego hacer algo como esto:

id *modalWindow = [self modalWindow]; 
if (modalWindow && [modalWindow level] != MY_DESIRED_MODAL_WINDOW_LEVEL) 
    [modalWindow setLevel: MY_DESIRED_MODAL_WINDOW_LEVEL]; 

Aparte de que incluso esto no funcionó bastante impecable - al cambiar de aplicaciones - que no se desea hacer esto de todos modos porque es un truco descarado y crudo.

Así que sí, lamentablemente será mejor que escriba su propia versión de NSAlert. Si realmente te importa esta posibilidad, me gustaría presentar un error al respecto. Es bastante extraño que [[alert window] setLevel: someLevel] no sea respetado por NSApplication y es un desperdicio tener que volver a compilar NSAlert con todas sus pequeñas características de diseño automático para poder hacer esto.

2

Lo que terminé haciendo fue abandonar NSAlert y en su lugar cargo una alerta NSWindow desde un NIB.

Este es el código que se muestra la ventana:

- (void)showAlert { 
    NSWindow *w = [self window]; 
    [w makeFirstResponder:nil]; 
    [w setLevel:NSFloatingWindowLevel]; 
    [w center]; 
    [w makeKeyAndOrderFront:self]; 
} 

Con ello se pretende hacerlo actuar como una alerta, excepto que también flota, y que no es modal, por lo que los elementos del menú se puede seleccionar mientras le corresponde.

¿Hay algo más que debería haber hecho?

Cuestiones relacionadas