2009-04-19 8 views
8

J'ai une application Cocoa qui affiche une alerte modale d'application en utilisant la classe NSAlert. Je voudrais que la fenêtre d'alerte flotte au-dessus de toutes les fenêtres des autres applications. Est-ce que cela peut être fait avec NSAlert, ou ai-je besoin d'implémenter ma propre fenêtre?NSAlert peut-il être utilisé pour créer une fenêtre flottante?

Je ne sais pas si cela est important, mais l'application est une application agent (LSUIElement est vrai) implémentée comme NSStatusItem. (Pour plus d'informations sur l'application, y compris le code source, regardez <here>.)

Voici le code qui affiche l'alerte:

- (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) { 
     // ... 
    } 
} 

J'ai essayé de mettre cela avant l'appel runModal:

[[alert window] setFloatingPanel:YES]; 

J'ai aussi essayé ceci:

[[alert window] setLevel:NSFloatingWindowLevel]; 

Mais neit Elle fait que la fenêtre reste au-dessus des autres si je clique sur la fenêtre d'une autre application. Je suppose que runModal ne respecte pas l'un ou l'autre de ces paramètres.

+1

chaque fois runModal est appelé remet à zéro le niveau de la fenêtre, pas sûr si cela aide ... – cobbal

Répondre

5

Je naufragé mon cerveau au sujet de cette chose exacte il y a un certain temps.

La seule façon que je pouvais obtenir ce travail (en quelque sorte), était sous-classe NSApplication, et passer outre -sendEvent. En -sendEvent, vous auriez d'abord appeler la mise en œuvre de super, faire quelque chose comme ceci:

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

En dehors de cela, même cela ne fonctionne pas tout à fait irréprochable - lorsque des applications de commutation - vous ne veux plus jamais faire de toute façon parce que c'est un hack flagrant et grossier.

Alors oui, malheureusement vous êtes mieux d'écrire votre propre version de NSAlert. Si vous vous souciez vraiment de cette possibilité, j'en ferais un bug. Il est assez bizarre que [[fenêtre d'alerte] setLevel: someLevel] ne soit pas respecté par NSApplication et c'est un gâchis d'avoir à recréer NSAlert avec toutes ses petites fonctionnalités de mise en page automatique juste pour pouvoir le faire.

2

Ce que j'ai fini par faire était d'abandonner NSAlert et à la place je charge un NSWindow alerte d'un NIB.

Voici le code qui affiche la fenêtre:

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

Ceci est destiné à faire agir comme une alerte, sauf qu'il flotte aussi, et il est non-modale, donc les éléments du menu peuvent être sélectionnés en c'est au programme.

Y at-il autre chose que je l'aurais fait?

Questions connexes