commandpalette — n_pbt_commandpalette #
← Référence des composants · Sommaire du guide
Palette de commandes : l'utilisateur presse un raccourci, tape trois lettres, et atteint n'importe quelle action de votre application — sans la chercher dans les menus.
▶ Le voir en vrai — Application de démonstration, tuile Command palette : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Objet | n_pbt_commandpalette — non visuel : rien à poser dans la fenêtre |
| Sert à | Rendre toutes les actions de l'application atteignables au clavier, en trois lettres |
| Retour | Non bloquant : of_open() rend la main aussitôt ; le choix revient par événement |
La palette est une fenêtre détachée, à elle : elle flotte au-dessus de votre application, prend le focus le temps que l'utilisateur tape, et le rend en se refermant.
Démarrage rapide #
// Une fois, au demarrage : les actions de votre application
inv_palette.ipo_owner = this
inv_palette.ipo_receiver = this
inv_palette.of_add_command(/*key*/ "new", /*label*/ "N", /*group*/ "F")
inv_palette.of_add_command(/*key*/ "open", /*label*/ "O", /*group*/ "F")
inv_palette.of_add_command(/*key*/ "save", /*label*/ "S", /*group*/ "F")
inv_palette.of_register_shortcut()
// event ue_command_selected : (string as_key)
choose case as_key
case "new"; of_nouveau()
case "open"; of_ouvrir()
case "save"; of_enregistrer()
end choose
Le câblage : le receveur #
Un objet non visuel n'a pas de handle de fenêtre : Windows ne sait pas à qui remettre les messages de la palette. C'est le rôle de ipo_receiver — un objet visuel, votre fenêtre par exemple, qui écoute et draine.
Trois lignes, une fois, à l'ouverture de la fenêtre :
inv_palette.ipo_owner = this // la fenetre a laquelle la palette appartient
inv_palette.ipo_receiver = this // celle qui recevra les evenements
inv_palette.of_register_shortcut() // la palette doit repondre a sa touche
Puis, sur le receveur, l'événement qui draine :
// event ue_palette_msg pbm_custom02
inv_palette.of_process_events()
Sans ce drainage, la palette s'ouvre et fonctionne, mais rien ne vous revient : ni le choix, ni l'ouverture, ni la fermeture.
Le raccourci : c'est la DLL qui l'entend #
Le raccourci qui ouvre la palette n'est pas écouté par la page : il est enregistré auprès de la DLL, qui seule voit les frappes pendant que le focus est sur un autre contrôle. C'est toute la différence entre une palette qu'on trouve et une palette qui ne répond que si on a déjà cliqué dessus.
La DLL entend l'accord, mais elle n'ouvre rien d'elle-même : elle vous prévient par ue_shortcut, et c'est vous qui décidez. Ouvrir une palette par-dessus un dialogue modal n'arrangerait personne.
// event ue_shortcut : la touche est tombee
if not ib_dialog_open then inv_palette.of_open()
is_shortcut choisit l'accord ; of_register_shortcut() le pose. Appelez-le une fois à l'ouverture de la fenêtre — sans quoi la palette ne répond à sa touche qu'après avoir déjà été ouverte une fois. of_open le repose au passage, donc un accord changé plus tard n'a besoin de rien de plus.
// Le raccourci de l'habitude, celui des editeurs de code
inv_palette.is_shortcut = inv_palette.SHORTCUT_DEFAULT
// Ou le votre
inv_palette.is_shortcut = "ctrl+shift+p"
// Ou aucun : la palette ne s'ouvre plus que par of_open()
inv_palette.is_shortcut = inv_palette.SHORTCUT_NONE
Deux composants qui demandent le même accord : celui qui a le focus gagne, sinon le premier enregistré. Le chapitre clavier le détaille.
Où la palette s'affiche #
is_position dit où la fenêtre se pose. Elle est toujours ramenée dans l'écran : une palette ancrée sous un champ en bas de fenêtre ne disparaît pas sous la barre des tâches.
| Constante | Où |
|---|---|
POSITION_WINDOW_CENTER | Centrée sur ipo_owner — le défaut, et ce qu'attend l'œil |
POSITION_SCREEN_CENTER | Centrée sur l'écran, quelle que soit la fenêtre |
POSITION_ABSOLUTE | À il_x / il_y, en pixels écran |
PowerBuilder travaille en PBU : convertissez avant de renseigner il_x / il_y.
Sa hauteur suit le nombre de commandes affichées, et se réduit à mesure que l'on filtre — sans que son coin haut bouge, sinon la zone de saisie se déroberait sous les doigts. Elle est plafonnée à la moitié de l'écran : au-delà, la liste défile à l'intérieur et la zone de saisie reste en haut.
Un clic ailleurs dans l'application referme la palette, et ce clic atteint quand même sa cible — comme un menu qu'on quitte. Rien à faire pour cela.
Propriétés #
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
ipo_owner | powerobject | — | La fenêtre à laquelle la palette appartient : elle possède la fenêtre popup et lui sert d'ancre. À poser avant of_open |
ipo_receiver | powerobject | — | L'objet visuel qui reçoit les événements. Il déclare event xxx pbm_custom02 et y appelle of_process_events |
is_shortcut | string | "ctrl+k" | Accord de touches qui ouvre la palette, depuis n'importe où dans la fenêtre. Constantes SHORTCUT_DEFAULT (ctrl+k) et SHORTCUT_NONE (aucun). Prend effet à of_register_shortcut |
is_position | string | window-center | Où la fenêtre se pose (constantes POSITION_*) |
il_x · il_y | long | 0 | Position en pixels écran, lue par POSITION_ABSOLUTE seulement |
is_placeholder | string | "" | Texte gris affiché dans la zone de saisie tant que rien n'est tapé |
is_recent | string | "" | Mémoire d'usage : les identifiants les plus récemment lancés, du plus récent au plus ancien, séparés par des virgules. La palette les fait remonter en tête, et la récence départage au filtrage — elle ne renverse jamais la pertinence. Relisez-la après usage et persistez-la ; reposez-la au démarrage. Une palette qui repart vierge chaque matin n'apprend rien |
il_max_recent | long | 8 | Combien le bloc « Récemment utilisé » en garde. 8 par défaut. 0 l'éteint : une application dont les utilisateurs préfèrent voir leurs groupes intacts peut le dire. Une entrée du bloc reste dans son groupe et y porte son nom — un raccourci ne déplace pas ce qu'il raccourcit |
Méthodes #
| Méthode | Rôle |
|---|---|
of_add_command (string as_key, string as_label, string as_group) | Déclare une action : son identifiant, son libellé, et le groupe sous lequel elle apparaît. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_add_command (string as_key, string as_label, string as_group, string as_hint, string as_shortcut, string as_keywords) | Même chose, avec l'explication à droite, le raccourci à afficher, qui lance sa commande tant que la palette est ouverte — c'est ainsi qu'on l'apprend ; en dehors, votre application garde ses propres accélérateurs — et des mots-clés que la recherche prend en compte sans qu'ils soient visibles. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_remove_command (string as_key) | Retire une action ; les autres restent. Renvoie 0 une fois appliqué, -5 sur un argument invalide (clé vide, adresse fausse), -2 si le composant n'est pas créé |
of_command (string as_key) → n_pbt_commandpalette_command | La poignée d'une commande, pour la renommer, changer son raccourci, la griser ou la masquer par ses propriétés. Griser plutôt que retirer : retirer ce que l'utilisateur ne peut pas faire lui retire aussi toute chance de découvrir que ça existe. L'état voyage avec les commandes : un changement fait palette ouverte se voit à l'ouverture suivante |
of_clear_commands ( ) | Vide la palette. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
of_count ( ) → integer | Combien de commandes la palette porte |
of_keys_at ( integer ai_index ) → string | L'identifiant de la commande de rang ai_index (à partir de 1), ou "" au-delà de l'un ou l'autre bout. Avec of_count, c'est ce qui permet de parcourir une palette qu'on n'a pas remplie soi-même — un module partagé y ajoute les siennes |
of_has ( string as_key ) → boolean | Une commande existe-t-elle sous cet identifiant ? Demander évite d'en déclarer une seconde sous un identifiant déjà pris |
of_open ( ) | Ouvre la palette : une fenêtre à elle, possédée par ipo_owner, placée par is_position. Elle prend le focus, et le rend en se refermant. Renvoie 0 une fois ouverte, -1 si le runtime WebView2 manque, -4 si sa fenêtre n'a pas pu être créée |
of_is_open ( ) | VRAI tant que la palette est à l'écran. C'est ce qui permet à l'accord de basculer : pressé une seconde fois, une palette se ferme — rappeler of_open détruirait la fenêtre pour la reconstruire à l'identique, ce qui se voit comme un clignotement, pas comme une fermeture. La DLL ne décide toujours rien : elle informe |
of_close ( ) | La referme. Perdre le focus la referme aussi, comme un menu. Renvoie 0 |
of_register_shortcut ( ) | Confie l'accord de is_shortcut à la DLL. À appeler une fois à l'ouverture de la fenêtre. Un seul accord par fenêtre : le rappeler après avoir changé is_shortcut remplace le précédent, qui cesse aussitôt de répondre — il n'y a jamais rien à retirer d'abord. Rend 0 s'il est posé, 1 s'il en a remplacé un, 2 si un is_shortcut vide l'a retiré |
of_process_events ( ) | Draine les événements en attente et les lève sur cet objet. À appeler depuis le pbm_custom02 de ipo_receiver — c'est le seul chemin de retour |
of_reset ( ) | Vide les commandes et remet les propriétés à leur défaut. ipo_owner et ipo_receiver sont laissés tels quels : c'est le câblage, pas le contenu. Renvoie 0 une fois appliqué, -2 si le composant n'est pas créé |
Propriétés d'une commande — n_pbt_commandpalette_command #
Obtenue par of_command(clé). La palette rebâtit sa fenêtre depuis sa liste à chaque of_open : une propriété changée pendant qu'elle est ouverte se voit à l'ouverture suivante.
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_label | string | — | Le texte de la ligne |
is_shortcut | string | "" | L'accord affiché à droite de la ligne, et honoré tant que la palette est ouverte (Ctrl+Shift+S) |
ib_enabled | boolean | true | Commande grisée : visible, cherchable, et inerte — ni clic, ni Entrée, ni son accord |
ib_visible | boolean | true | Commande masquée : hors de la liste et des accords, sans être retirée ; elle revient telle quelle |
Événements #
| Événement | Déclenché quand |
|---|---|
ue_command_selected (string as_key) | L'utilisateur a choisi une action. La palette s'est déjà refermée : à vous de faire ce qu'elle annonce |
ue_shortcut ( ) | L'accord a été pressé. La DLL relaie, PB décide. Une palette bascule sur sa propre touche : if of_is_open() then of_close() else of_open(). Vous pouvez aussi refuser |
ue_opened ( ) | La palette est à l'écran — par of_open |
ue_closed ( ) | Elle vient de se refermer, choix fait ou non |
La palette ne fait rien d'elle-même. Elle rapporte l'identifiant choisi, et referme. C'est votre application qui agit — la même action, déclenchée depuis un menu ou depuis la palette, passe donc par le même code.
Au clavier #
| Touche | Effet |
|---|---|
L'accord de is_shortcut | Prévient votre code par ue_shortcut ; c'est lui qui ouvre |
| Frappe au clavier | Filtre au fil de la saisie : les lettres tapées n'ont pas à se suivre, nvf trouve « Nouveau fichier » |
| Flèches haut / bas | Déplacent la sélection dans la liste |
| Entrée | Choisit l'action sélectionnée (ue_command_selected) |
| Le raccourci affiché sur une ligne | Lance cette commande, sans avoir à la sélectionner |
| Échap | Referme sans rien choisir |
Exemples #
Alimenter la palette depuis votre menu #
// Les mots-cles ne s'affichent pas, mais la recherche les lit :
// taper "pdf" trouvera l'export meme si le libelle ne le dit pas
inv_palette.of_add_command(/*key*/ "export", /*label*/ "E", /*group*/ "F", /*hint*/ "H", /*shortcut*/ "Ctrl+E", /*keywords*/ "pdf csv xlsx")
Choisir un autre raccourci #
// Ctrl+K est deja pris par votre application ? Choisissez-en un autre.
// of_register_shortcut le pose, et l'ancien s'en va tout seul.
inv_palette.is_shortcut = "ctrl+shift+p"
inv_palette.of_register_shortcut()
L'ancrer sous un champ #
// Ancree sous un champ de saisie : PB compte en PBU, la DLL en pixels
// La palette est ramenee dans l'ecran si elle depassait
inv_palette.is_position = inv_palette.POSITION_ABSOLUTE
inv_palette.il_x = UnitsToPixels(sle_1.x, XUnitsToPixels!)
inv_palette.il_y = UnitsToPixels(sle_1.y + sle_1.height, YUnitsToPixels!)
inv_palette.is_placeholder = "P"
inv_palette.of_open()
inv_palette.of_remove_command(/*key*/ "print")
inv_palette.of_clear_commands()
inv_palette.of_close()
Bonnes pratiques #
- Donnez à chaque commande le même identifiant que dans votre menu : une seule fonction traite les deux, et l'utilisateur obtient exactement la même chose.
- Appelez
of_register_shortcut()à l'ouverture de la fenêtre, pas au premierof_open: une palette qui ne répond à sa touche qu'après avoir été ouverte à la souris ne sert à rien. - Renseignez les mots-clés : c'est ce qui fait la différence entre une palette qu'on utilise et une palette où l'on ne trouve rien. Pensez aux mots que l'utilisateur emploie, pas aux vôtres.
- Affichez le raccourci de l'action dans
as_shortcut: la palette devient alors le moyen de les apprendre. - N'y mettez que des actions immédiates. Une commande qui ouvre un dialogue de configuration, oui ; une commande qui a besoin de trois paramètres, non.
- Retirez les commandes qui n'ont plus de sens plutôt que de les laisser échouer : une palette qui propose l'impossible perd la confiance en une fois.