gèrer le menu d'une application par programmation, sans IB
bofy
Membre
Je crée un project "toto" avec xcode, application cocoa standard.
Mon main.m modifié :
Tout marche parfaitement, naturellement mon appli ne fait rien :
- elle affiche un menu "toto" à droite de la pomme
- l'icône habituelle dans la barre des tâches avec "toto"
Maintenant, je veux :
- au lieu de "toto" que ce soit "tata" qui s'affiche
- ajouter un sous-menu, avec l'item "quit"
NB :
- je sais parfaitement faire tout ce qui est proposé dans le fil "nib minimal"
de Philippe49...
- il semble qu'il y ait un "rootmenu" imposé dont la clé est introuvable pour moi
(les méthodes mainMenu, supermenu, etc. ne donnent rien)
PS :
- je comprends toujours aussi mal que ce soit aussi compliqué de trouver
comment faire par programmation ce qu'on fait avec IB (par vraiment
simplement d'ailleurs)
- l'expérience de mon insistance à me passer de IB me montre en fait que
la programmation n'est pas si compliquée que ça, une fois qu'on a les clés
Mon main.m modifié :
<br />#import <Cocoa/Cocoa.h><br />int main(int argc, char *argv[]) {<br /> [NSApplication sharedApplication];<br /> [NSApp run];<br /> return 0;<br /> }<br />
Tout marche parfaitement, naturellement mon appli ne fait rien :
- elle affiche un menu "toto" à droite de la pomme
- l'icône habituelle dans la barre des tâches avec "toto"
Maintenant, je veux :
- au lieu de "toto" que ce soit "tata" qui s'affiche
- ajouter un sous-menu, avec l'item "quit"
NB :
- je sais parfaitement faire tout ce qui est proposé dans le fil "nib minimal"
de Philippe49...
- il semble qu'il y ait un "rootmenu" imposé dont la clé est introuvable pour moi
(les méthodes mainMenu, supermenu, etc. ne donnent rien)
PS :
- je comprends toujours aussi mal que ce soit aussi compliqué de trouver
comment faire par programmation ce qu'on fait avec IB (par vraiment
simplement d'ailleurs)
- l'expérience de mon insistance à me passer de IB me montre en fait que
la programmation n'est pas si compliquée que ça, une fois qu'on a les clés
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Impossible. OSX fonctionne comme ça et ce n'est pas négociable.
Le nom de ton menu toto provient de la clé "CFBundleName" du fichier "info.plist".
Le truc de créer un menu et d'insérer un item a déjà été donné dans un autre sujet.
Pour modifier le menu toto, t'as juste à créer un nouveau menu avec comme nom le symbole "APPLE". Ce menu écrasera le menu toto créé automatiquement.
Mais je le rappelle, ça va créer un nouveau menu toto avec ton propre contenu mais sans pouvoir changer son nom.
Comme ça a été dit, la barre de menu d'une appli cocoa est créée via carbon.
En cocoa, la méthode mainMenu renvoie cette barre sous forme d'un objet NSMenu. Mais mainMenu n'est valide qu'en fin d'initialisation de l'appli.
Pour accéder à cette barre dans les cas où mainMenu est nil, faut utiliser la fonction carbon AcquireRootMenu().
Mais la barre de menu du point de vue application ne contient pas le menu pomme, le menu application, et les menus à droites (spotlight, etc.).
Il n'existe aucune méthode officielle pour toucher aux parties de la barre de menu qui ne sont pas accessibles en tant qu'appli.
C'est comme ça, ou alors, change d'OS si ça ne convient pas.
Une appli cocoa a besoin d'un mainMenu.nib.
C'est comme ça que ça a été prévu par Apple, et c'est documenté.
Tout le reste c'est de la bidouille, donc il faut pécher les infos.
C'est bien d'avoir les clés.
Mais faut aussi respecter la notice d'utilisation qui est avec.
Sinon la clé tournera mal dans la serrure.
Un peu de polémique :
Je pense que la programmation objet (ou dite objet) est le contraire de la bidouille. C'est même l'un des avantages vantés de ce type de programmation : une fois qu'un objet est testé et validé, en principe plus de problèmes. Par contre la programmation graphique, qui impose de reproduire les mêmes adaptations à chaque nouvelle application, est source d'erreurs, car on ne peut ni tout mémoriser, ni tout noter à chaque nouvel essai, en plus elle ne permet pas de comprendre ce qu'on fait.
Pour tout un grand merci :
Tu m'a permis de comprendre comment marchent les menus d'application (mélange de Cocoa et de Carbon) et de les construire à ma guise (sans IB naturellement !).
Si tu changes le info.plist de ton projet, il faut le recompiler totalement (par un "clean all targets" je crois).
Ensuite, il faut simuler une install de l'appli pour forcer le launch service à reconstruire ses caches (va dans le répertoire build de ton projet, repère l'appli, puis déplace là via le Finder dans un autre répertoire).
Maintenant, en l'absence de clé "CFBundleName", je ne sais pas comment le système va réagir (va t'il chercher le nom de l'appli autre part ?).
Il n'y a pas de polémique.
Même en prog objet, les problèmes que tu évoques sont possibles.
Cocoa date de Next, or il évolue constamment. Nombre de classes ou de méthodes sont devenues "deprecated" au fil des versions.
Concernant le gestion des menus... Cocoa implante une gestion des menus, mais à la mode Next.
Quand Apple a pondu OSX à partir de Next, il n'a pas pu reprendre cette gestion des menus, car elle était en désaccord avec celle propre à MAC OS (et ceci depuis Système 1).
Je pense que par raccourci, les ingénieurs de la Pomme ont repris le code de gestion des menus (le menu manager) tel quel. Ce code appartenait à la toolbox puis à Carbon. Cocoa a était "tordu" afin de rentrer dans ce moule : c'est pourquoi des classes commes NSMenuView et NSMenuItemCell qui permettaient de personnaliser l'affichage des menus n'ont jamais été fonctionnelles (car trop éloignées de la manière dont le menu manager dessine ses menus).
Le truc du symbole "POMME" pour faire le menu applications date de Système 1 (où ce menu s'appelait... menu Pomme). Il a été repris et mis au gout du jour (l'équivalent du menu Pomme d'avant étant le menu Application d'aujourd'hui).
Le problème de ce truc est que s'est documenté dans les IM (Inside Macintosh) mais pas dans la doc Cocoa.
Juste deux questions
1. comment récupérer le nom de l'appli ? CFBundleName ne semble pas fiable ? sinon comment utiliser cette variable, j'ai oublié (un début d'Alzheimer ?)
2. comment (idem) vider le cache de NSLog() afin de n'être pas obligé de lancer plusieurs fois l'appli (j'ai cherché, mais je n'ai pas trouvé grand chose sur NSLog, hors du formatage évident)
Par défaut le nom de l'appli tel qu'il apparait dans le moniteur d'activité, dans le menu pomme ("forcer à quitter") ou dans le titre du menu de l'application provient de CFBundleName de info.plist.
Si cette clé n'est pas trouvée, alors le système utilise comme nom d'appli le contenu de la clé CFBundleExecutable. Généralement elles sont identiques. Si cette dernière clé n'est pas trouvée, alors l'appli refuse de se lancer (message "appli endommagée").
Pour récupérer le contenu de "info.plist" dans le programme, faut utiliser la méthode objectForInfoDictionaryKey: de la classe NSBundle :
Je ne comprends pas la question.
Quel cache ? Quel est le problème avec NSLog() ?
Merci à tous