PBToolboxAI v4 ← Site

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 #

Objetn_pbt_commandpalette — non visuel : rien à poser dans la fenêtre
Sert àRendre toutes les actions de l'application atteignables au clavier, en trois lettres
RetourNon 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.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_new()
	case "open"; of_open()
	case "save"; of_save()
end choose

Le branchement : la fenêtre hôte #

La palette est un objet non visuel, mais vous n'avez aucun receveur ni message à câbler : réglez ipo_owner sur votre fenêtre, et la palette draine elle-même ses événements et les lève sur cet objet.

Deux lignes, une fois, à l'ouverture de la fenêtre :

// La fenetre a laquelle la palette appartient
inv_palette.ipo_owner = this

// La palette doit repondre a sa touche
inv_palette.of_register_shortcut()

C'est tout ce qu'il y a à brancher. Le choix de l'utilisateur, l'ouverture et la fermeture vous reviennent ensuite par de simples événements sur ipo_owner — sans receveur, sans message à mapper, sans timer.


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

L'accord de la palette n'est consulté qu'après les raccourcis des autres composants de la fenêtre, focus ou non : un bouton de barre d'outils posé sur le même accord l'emporte. L'accord de cette fenêtre passe avant un accord posé sans ipo_owner (toute l'application). Seules les touches que le crochet sait nommer sont acceptées — lettres, chiffres, F1 à F24, Entrée, Échap, Suppr, Inser, Début, Fin, Pg préc., Pg suiv. et, avec Ctrl ou Alt, les flèches, Espace, Tab, Retour arrière, + - , . ; toute autre rend -5. 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.

ConstanteOù
POSITION_WINDOW_CENTERCentrée sur ipo_owner — le défaut, et ce qu'attend l'œil
POSITION_SCREEN_CENTERCentrée sur l'écran, quelle que soit la fenêtre
POSITION_ABSOLUTEÀ il_x / il_y, en pixels écran

PowerBuilder travaille en PBU, et la position d'un contrôle est relative à sa fenêtre : pour ancrer la palette sous un contrôle, of_anchor_under(contrôle) fait la conversion et pose les trois propriétés. Sur deux écrans, elle s'ouvre sur l'écran du point demandé.

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éTypeDéfautRôle
ipo_ownerpowerobject—La fenêtre à laquelle la palette appartient : elle possède la fenêtre popup et lui sert d'ancre, son accord répond dans cette fenêtre, et c'est sur elle que les événements de la palette sont levés. À poser avant of_open — c'est le seul branchement à faire. Laissée vide, l'accord répond dans toutes les fenêtres de l'application. Deux objets palette posés sur la même fenêtre gardent chacun leur accord et leurs événements : aucun ne reçoit ceux de l'autre
ipo_receiverpowerobject—Optionnel, hérité : un objet visuel distinct sur lequel livrer les événements, à la place de ipo_owner — c'est aussi la seule fenêtre dont le pbm_custom02 est sonné à chaque événement. Laissez-le vide — la palette livre désormais ses événements toute seule via ipo_owner
is_shortcutstring"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_positionstringwindow-centerOù la fenêtre se pose (constantes POSITION_*)
il_x · il_ylong0Position en pixels écran, lue par POSITION_ABSOLUTE seulement
is_placeholderstring""Texte gris affiché dans la zone de saisie tant que rien n'est tapé
is_recentstring""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_recentlong8Combien 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éthodeRô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 ajoutée, -5 si la clé est vide, contient /, ` ou une virgule (is_recent` est une liste séparée par des virgules), ou est déjà prise. Des dizaines de milliers de commandes restent fluides : la palette ne dessine que les lignes visibles
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 pendant la frappe Ctrl+C, Ctrl+V, Ctrl+Z et Ctrl+A restent à la zone de recherche — et des mots-clés que la recherche prend en compte sans qu'ils soient visibles. Renvoie 0 une fois ajoutée, -5 si la clé est vide, contient /, ` ou une virgule (is_recent` est une liste séparée par des virgules), ou est déjà prise
of_insert_command (string as_key, string as_label, string as_group, integer ai_index)Déclare une action à un rang choisi (1 = en tête) plutôt qu'à la fin : un module partagé range ses commandes où elles vont. 0 ou moins, ou au-delà de la fin, ajoute au bout. Indication, raccourci, mots-clés et icône se posent ensuite par of_command. Renvoie 0 une fois ajoutée, -5 pour les mêmes clés que of_add_command
of_remove_command (string as_key)Retire une action ; les autres restent. Renvoie 0 une fois retirée, -5 si aucune commande ne porte cette clé
of_command (string as_key) → n_pbt_commandpalette_commandLa 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_key ( ) → stringSur la poignée que rend of_command : la clé de la commande qu'elle désigne — ce qu'of_command a reçu pour l'obtenir, et ce qu'on garde quand la poignée passe de main en main
of_clear_commands ( )Vide la palette. Renvoie 0
of_count ( ) → longRend le nombre de commandes que la palette porte
of_keys_at ( long al_index ) → stringL'identifiant de la commande de rang al_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 ) → booleanUne commande existe-t-elle sous cet identifiant ? Demander vaut mieux que deviner : of_add_command refuse (-5) un identifiant déjà pris
of_anchor_under ( dragobject ado_control )Ancre la palette sous un contrôle — un champ, un bouton : pose is_position à POSITION_ABSOLUTE et il_x / il_y sur le coin bas gauche du contrôle, en pixels écran. À appeler avant of_open ; la palette reste ramenée dans l'écran. Renvoie 0, ou -5 si le contrôle n'est pas valide
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 demandée — ue_opened (à l'écran) ou ue_closed (avec la raison pour laquelle elle n'a pas paru) suit toujours —, -6 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. Une fois ouverte, la palette tient le focus dans sa propre fenêtre : l'accord pressé là la referme d'elle-même. Il répond pour la palette de cet objet : quand un autre objet palette ouvre la sienne, elle remplace celle-ci et of_is_open répond FAUX ici
of_close ( )Referme la palette que cet objet a ouverte — jamais celle qu'un autre objet palette a ouverte depuis. 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 objet palette : 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 ne laisse aucun accord (retiré, ou il n'y en avait pas), -5 si la touche est de celles que le crochet ne voit pas (voir plus haut) — l'accord précédent est alors gardé. Sans ipo_owner, l'accord répond dans toutes les fenêtres de l'application. Deux objets palette d'une même fenêtre gardent chacun le leur ; le même accord posé par un second objet lui revient (1). Détruire l'objet retire son accord — jamais celui qu'un autre objet palette tient
of_process_events ( )Draine les événements en attente et les lève sur ipo_owner. Le composant l'appelle lui-même tant que la palette vit : vous n'avez normalement pas à le faire
of_reset ( )Vide les commandes et la mémoire d'usage (is_recent), remet les propriétés à leur défaut, referme une palette ouverte et ramène un accord posé à SHORTCUT_DEFAULT. ipo_owner et ipo_receiver sont laissés tels quels : c'est le câblage, pas le contenu

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éTypeDéfautRôle
is_labelstring—Le texte de la ligne
is_shortcutstring""L'accord affiché à droite de la ligne, et honoré tant que la palette est ouverte (Ctrl+Shift+S)
is_groupstring—Le groupe sous lequel la commande est rangée ; le changer la déplace sans la retirer (elle garde son rang parmi les commandes)
is_hintstring""La petite ligne sous le libellé
is_keywordsstring""Les mots que la recherche lit sans les montrer — les mots de l'utilisateur
is_iconstring""Une icône à gauche de la ligne : un fichier, une image de bibliothèque, ou mono: / tint: pour une icône qui suit le thème
ib_enabledbooleantrueCommande grisée : visible, cherchable, et inerte — ni clic, ni Entrée, ni son accord
ib_visiblebooleantrueCommande masquée : hors de la liste et des accords, sans être retirée ; elle revient telle quelle

Événements #

ÉvénementDé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() — pressé dans la palette ouverte, l'accord la referme de lui-même. Vous pouvez aussi refuser
ue_opened ( )La palette est à l'écran — par of_open
ue_closed (string as_reason)Elle vient de se refermer, choix fait ou non. Il suit chaque of_open qui a rendu 0 : as_reason est vide pour une palette qui était à l'écran, cancelled si elle a été fermée — ou remplacée par une autre palette — avant de paraître, failed si sa fenêtre n'a pas pu naître, blocked sous débogage distant sans licence

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 #

ToucheEffet
L'accord de is_shortcutPrévient votre code par ue_shortcut ; c'est lui qui ouvre
Frappe au clavierFiltre au fil de la saisie : les lettres tapées n'ont pas à se suivre, nvf trouve « Nouveau fichier », et les accents ne comptent pas (preferences trouve « Préférences »)
Flèches haut / basDéplacent la sélection dans la liste
EntréeChoisit l'action sélectionnée (ue_command_selected)
Le raccourci affiché sur une ligneLance cette commande, sans avoir à la sélectionner
ÉchapReferme 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, en pixels ecran
// La palette est ramenee dans l'ecran si elle depassait
inv_palette.of_anchor_under(/*control*/ sle_1)
inv_palette.is_placeholder = "P"
inv_palette.of_open()
// Remove one command, empty the list, close the palette
inv_palette.of_remove_command(/*key*/ "print")
inv_palette.of_clear_commands()
inv_palette.of_close()

Bonnes pratiques #


← Référence des composants · Sommaire du guide