toaster — n_pbt_toaster #
← Référence des composants · Sommaire du guide
Notifications « toast » en coin d'écran : un message qui apparaît, informe et disparaît sans bloquer l'utilisateur ni interrompre sa saisie.
▶ Le voir en vrai — Application de démonstration, tuile Toaster : l'aperçu, le code qui le produit et cette page, côte à côte.
En bref #
| Objet | n_pbt_toaster — non visuel : rien à poser dans la fenêtre |
| Sert à | Confirmer une action réussie, signaler un avertissement ou une erreur, sans arrêter le travail en cours |
| Retour | Non bloquant : of_show() rend la main immédiatement ; les réactions de l'utilisateur reviennent par événements |
Le toast est une fenêtre détachée : il flotte au-dessus de votre application (ou de tout l'écran) et se referme tout seul.
// Variables locales
n_pbt_toaster lnv_toast
// Creer le notificateur
lnv_toast = create n_pbt_toaster
// ... configuration ...
// Le detruire une fois termine
destroy lnv_toast
Démarrage rapide #
// Variables locales
n_pbt_toaster lnv_toast
// Creer le notificateur
lnv_toast = create n_pbt_toaster
// Configurer puis afficher
lnv_toast.ipo_owner = this // fenetre a laquelle le toast s'accroche
lnv_toast.is_kind = lnv_toast.KIND_SUCCESS // icone verte + lisere de succes
lnv_toast.is_text = "Vos modifications ont ete [b]enregistrees[/b]."
lnv_toast.of_show()
// Le detruire une fois termine
destroy lnv_toast
Tout se configure par propriétés, puis of_show() — qui ne prend aucun argument — fait apparaître la notification. Le toaster ci-dessus est détruit tout de suite : rien ne revient, et c'est voulu pour une simple confirmation. Pour recevoir les retours d'un toast, voir « Où écrire les événements ».
Propriétés #
À poser avant of_show.
| Propriété | Type | Défaut | Rôle |
|---|---|---|---|
is_text | string | "" | Corps du message. Accepte le balisage riche |
is_kind | string | KIND_INFO | Niveau : pilote l'icône et la couleur du liseré. Constantes KIND_* |
is_position | string | POSITION_BOTTOM_RIGHT | Coin d'ancrage. Constantes POSITION_* |
ib_screen | boolean | false | false = ancré au coin de la fenêtre ; true = ancré au coin de l'écran, flottant au-dessus de tout. Les toasts ancrés à l'écran s'empilent par moniteur : deux fenêtres qui en montrent chacune un ne se recouvrent plus |
il_timeout | long | TIMEOUT_AUTO | Durée d'affichage en millisecondes avant fermeture automatique. TIMEOUT_AUTO (-1, le défaut) vaut 4 s pour une information mais jusqu'au clic pour une erreur — une erreur qui s'efface en quatre secondes est une erreur perdue. TIMEOUT_UNTIL_CLICKED (0) rend n'importe quel toast persistant ; une durée explicite est respectée telle quelle. Tant que le pointeur reste sur un toast, son compte à rebours est suspendu, et une barre montre le temps restant |
is_title | string | "" | Ligne de titre en gras au-dessus du message (toast enrichi) |
is_image | string | "" | Image d'illustration à gauche, à la place de l'icône de niveau (formes acceptées : chemin, mono:, ressource de DLL) |
is_key | string | "" | Clé du toast : réafficher la même clé met à jour le toast déjà à l'écran au lieu d'en ouvrir un second. C'est ce dont une notification de progression a besoin (« Export 3/10 » puis « 4/10 ») : fermer et rouvrir relancerait l'animation et ferait sauter la pile. Laissez vide pour un toast ordinaire. La clé appartient au toaster : un autre toaster qui montre la même clé ouvre son propre toast. Une mise à jour reprend aussi le coin, l'ancrage à l'écran et la fenêtre d'ancrage. La clé revient en as_key dans les événements ue_toast_* |
is_sound | string | SOUND_AUTO | Son système du toast, joué quand il est demandé. SOUND_AUTO (le défaut) : une erreur ou un avertissement sonne, une information ou un succès reste muet ; SOUND_ALWAYS : toutes les natures ; SOUND_NEVER : silence |
il_max_visible | long | 0 | Nombre maximal de toasts à l'écran au même coin (1 à 20). Au-delà, les suivants attendent et apparaissent à mesure que la place se libère : une boucle de traitement qui émet un toast par ligne empilait sinon les fenêtres hors de l'écran. Ce plafond est commun à tous les toasters de l'application : la dernière valeur posée l'emporte ; 0 (le défaut) le laisse tel quel — 5 tant que personne ne l'a posé. Une pile, c'est le même coin de la même fenêtre — ou, pour un toast ancré à l'écran ou sans ipo_owner, le même coin du même moniteur, quelle que soit la fenêtre qui l'a montré. Un toast qui ne tiendrait plus à l'écran attend lui aussi, et un toast n'est jamais plus haut que l'écran : son texte défile |
ipo_owner | powerobject | — | L'objet visuel auquel le toast est accroché (le coin de la zone cliente de sa fenêtre sert de repère : sous la barre de titre ; dans un cadre MDI, la zone cliente du cadre, barres d'outils et MicroHelp laissées libres). C'est le seul branchement à faire : les événements du toast sont levés sur le toaster lui-même. Tant que cette fenêtre est réduite, le toast attend : il ne s'affiche pas et son compte à rebours ne tourne pas avant qu'elle revienne |
ipo_receiver | powerobject | — | Optionnel, hérité : posé, sa fenêtre voit son pbm_custom02 sonner à chaque événement de toast (pour un code ancien qui l'avait branché). Laissez-le vide — le toaster livre ses événements tout seul, sur lui-même |
Constantes #
| Constante | Valeur | Usage |
|---|---|---|
KIND_INFO | "info" | Information neutre |
KIND_SUCCESS | "success" | Opération réussie |
KIND_WARNING | "warning" | Avertissement |
KIND_ERROR | "error" | Échec |
POSITION_TOP_LEFT | "top-left" | Coin haut gauche |
POSITION_TOP_CENTER | "top-center" | Haut, centré |
POSITION_TOP_RIGHT | "top-right" | Coin haut droit |
POSITION_BOTTOM_LEFT | "bottom-left" | Coin bas gauche |
POSITION_BOTTOM_CENTER | "bottom-center" | Bas, centré |
POSITION_BOTTOM_RIGHT | "bottom-right" | Coin bas droit (défaut) |
SOUND_AUTO | "auto" | Son pour une erreur ou un avertissement seulement (défaut) |
SOUND_ALWAYS | "always" | Son pour toutes les natures |
SOUND_NEVER | "never" | Jamais de son |
REASON_TIMEOUT | "timeout" | ue_toast_dismissed : son délai s'est écoulé |
REASON_USER | "user" | ue_toast_dismissed : l'utilisateur a cliqué sa croix |
REASON_CODE | "code" | ue_toast_dismissed : of_close ou of_close_all l'a fermé |
REASON_OWNER_CLOSED | "owner" | ue_toast_dismissed : la fenêtre à laquelle il était ancré s'est fermée |
Pourquoi
LEFT/RIGHTici, etSTART/ENDailleurs ? Le toast est une fenêtre système posée en pixels écran, pas un contenu qui suit un sens de lecture : un coin d'écran n'a pas de « début ». Ces constantes restent donc volontairement physiques, et ne changent pas de côté quand l'application passe en écriture de droite à gauche. Voir Langue et RTL.
Méthodes #
| Méthode | Rôle |
|---|---|
of_show ( ) → long | Affiche la notification construite à partir des propriétés. Renvoie l'identifiant du toast (> 0) — un toast qui attend sa place (il_max_visible) a lui aussi le sien, tout de suite —, ou une valeur négative en cas d'erreur. Ne bloque pas. -5 (et rien ne s'affiche) pour un réglage hors de ses bornes : un is_kind, is_position ou is_sound qui n'est aucune de ses constantes, il_max_visible hors de 0 à 20, il_timeout sous TIMEOUT_AUTO ; -4 : pas affiché cette fois — le moteur d'affichage n'est pas encore prêt (réessayer), ou la file d'attente est pleine ; -6 : runtime WebView2 absent. of_get_last_error dit pourquoi |
of_close ( long al_id ) → long | Ferme un toast de ce toaster, désigné par l'identifiant rendu par of_show — affiché, pas encore dessiné, ou qui attend encore sa place. Chaque toast fermé ainsi lève ue_toast_dismissed avec REASON_CODE, même fermé juste après of_show. Renvoie 0, ou -5 (of_get_last_error dit pourquoi) si l’identifiant est vide, désigne un toast déjà disparu ou déjà en fermeture, ou un toast d'un autre toaster |
of_close_all ( ) → long | Ferme tous les toasts de ce toaster — affichés, pas encore dessinés ou en attente —, et rien d'un autre toaster. Chacun lève ue_toast_dismissed avec REASON_CODE. Renvoie le nombre de toasts fermés (0 s'il n'y en avait aucun) |
of_get_last_error ( ) → string | Pourquoi le dernier of_show ou of_close a refusé — "" s'il n'a rien refusé. À lire après un retour négatif : un réglage hors de ses bornes, le moteur d'affichage pas encore prêt, un toast d'un autre toaster… |
of_reset ( ) → long | Remet toutes les propriétés de contenu à leur défaut et efface les boutons (ipo_owner et ipo_receiver sont conservés : ce sont des branchements, pas du contenu) Rend 0 une fois fait. |
of_process_events ( ) | Vide la file des retours du toast et lève les événements ue_toast_* correspondants. Le composant l'appelle lui-même tant qu'un toast est à l'écran : vous n'avez normalement pas à le faire — voir ci-dessous |
of_add_button (string as_key, string as_label {, string as_image }) → long | Ajoute un bouton d'action (3 au plus). Un clic dessus émet ue_toast_action(id, cle, action) ; of_reset efface les boutons. Un libellé peut contenir n'importe quel caractère — une virgule, un signe égal — sans être coupé. Renvoie 0, ou -5 (rien n'est ajouté) pour une clé vide, une clé déjà prise, une clé qui contient / ou une barre verticale, ou un quatrième bouton |
of_count ( ) → long | Rend le nombre de boutons d'action que la notification porte |
of_keys_at ( long al_index ) → string | La clé du bouton de rang al_index (à partir de 1), ou "" au-delà de l'un ou l'autre bout |
of_has ( string as_key ) → boolean | Un bouton a-t-il été ajouté sous cette clé ? of_add_button refuse (-5) une clé déjà prise : demander d'abord dit pourquoi |
Plusieurs toasts affichés au même coin s'empilent automatiquement. Chacun porte une croix de fermeture ; l'identifiant renvoyé par of_show permet de les distinguer dans les événements et de les fermer depuis votre code.
Le compte à rebours se met en pause tant que le pointeur est sur le toast : une notification ne doit pas s'évanouir sous les yeux de qui la lit. Une fine barre en bas du toast montre le temps restant — et explique donc sa disparition. Un clic sur le corps répond et ferme.
Une notification posée avec il_timeout = 0 reste à l'écran tant que personne ne la ferme : gardez son identifiant pour pouvoir la retirer quand la tâche qu'elle annonce est terminée.
// Variables locales
long ll_toast
// Notification persistante : elle restera affichee jusqu'a of_close.
inv_toaster.is_text = "Export en cours..."
inv_toaster.il_timeout = /*ms, 0 = pas de fermeture auto*/ 0
ll_toast = inv_toaster.of_show()
// ... traitement long ...
// Fermer le toast une fois le travail fini
inv_toaster.of_close(/*id*/ ll_toast)
Événements — le toast vous répond #
Une notification n'est pas un simple « affiche et oublie » : elle peut vous dire qu'elle a été cliquée, qu'un bouton d'action a été choisi, ou qu'elle s'est fermée.
Vous n'avez rien à câbler pour cela : réglez ipo_owner (la fenêtre à laquelle le toast est ancré) et traitez les événements. Le composant les draine lui-même tant qu'un toast est à l'écran et les lève sur l'objet — ni receveur, ni timer.
Où écrire les événements #
PowerBuilder n'offre les événements d'un objet non visuel qu'à deux endroits : un descendant de n_pbt_toaster (ses événements portent vos scripts), ou un toaster posé sur la fenêtre comme tout objet non visuel (dans le peintre de fenêtre, Insert > Object, puis n_pbt_toaster : ses événements se scriptent dans la fenêtre). Une variable n_pbt_toaster créée par create n'a aucun script : ses toasts s'affichent, mais leurs retours n'arrivent à personne. Et un toaster détruit ne rapporte plus rien : ses toasts persistants et ceux qui portent des boutons se ferment avec lui, les autres finissent seuls, muets. Avec un descendant n_my_toaster, la fenêtre en garde un dans une variable d'instance inv_toaster :
// Event open de la fenetre : creer le toaster une fois et l'ancrer
inv_toaster = create n_my_toaster
inv_toaster.ipo_owner = this
1. Régler ipo_owner sur la fenêtre à laquelle le toast est ancré :
// Ancrer les toasts a cette fenetre
inv_toaster.ipo_owner = this // la fenetre a laquelle le toast est ancre
2. Traiter les événements levés sur le toaster :
| Événement | Déclenché quand |
|---|---|
ue_toast_clicked (long al_id, string as_key) | Le corps du toast est cliqué (pas un bouton). al_id est l'identifiant rendu par of_show, as_key le is_key du toast (vide sans clé) |
ue_toast_action (long al_id, string as_key, string as_action) | Un bouton d'action est cliqué ; as_action vaut la clé passée à of_add_button. al_id est l'identifiant rendu par of_show, as_key le is_key du toast (vide sans clé) |
ue_toast_dismissed (long al_id, string as_key, string as_reason) | Le toast se ferme ; as_reason dit pourquoi : REASON_TIMEOUT (délai écoulé), REASON_USER (croix de fermeture), REASON_CODE (of_close ou of_close_all, que le toast soit affiché, pas encore dessiné ou en attente), REASON_OWNER_CLOSED (la fenêtre d'ancrage s'est fermée). Un clic sur le corps lève ue_toast_clicked, un bouton ue_toast_action. al_id est l'identifiant rendu par of_show, as_key le is_key du toast (vide sans clé) |
Si vous n'attendez aucun retour — ni bouton d'action, ni clic sur le corps — vous n'avez aucun de ces événements à traiter : la notification s'affiche et disparaît toute seule. C'est le mode le plus simple, parfait pour une simple confirmation.
Exemples #
Les quatre niveaux #
// Info : un message neutre
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_INFO
inv_toaster.is_text = "Operation terminee."
inv_toaster.of_show()
// Succes : c'est fait
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Vos modifications ont ete [b]enregistrees[/b]."
inv_toaster.of_show()
// Avertissement : a regarder
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_WARNING
inv_toaster.il_timeout = 5000 // un peu plus long
inv_toaster.is_text = "Espace disque faible sur le lecteur C:."
inv_toaster.of_show()
// Erreur : c'est un echec ; elle reste jusqu'au clic
inv_toaster.of_reset()
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.is_text = "Impossible de joindre le serveur."
inv_toaster.of_show()
Choisir le coin, dans la fenêtre ou sur l'écran #
// Ancre au coin haut droit de la FENETRE (defaut : suit l'application)
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = false
inv_toaster.is_text = "Ancre au coin de la fenetre."
inv_toaster.of_show()
// Detache : ancre au coin de l'ECRAN, visible meme si la fenetre est reduite
inv_toaster.is_position = inv_toaster.POSITION_TOP_RIGHT
inv_toaster.ib_screen = true
inv_toaster.is_text = "Traitement de nuit termine."
inv_toaster.of_show()
Toast enrichi : titre, image et durée #
// Repartir des reglages par defaut
inv_toaster.of_reset()
// Un titre, un texte et une image
inv_toaster.is_title = "Sauvegarde terminee"
inv_toaster.is_text = "1 240 fichiers copies vers [b]\\serveur\backup[/b]."
inv_toaster.is_image = "mono:img\backup.svg"
inv_toaster.il_timeout = 8000 // reste 8 secondes
inv_toaster.of_show()
Notification avec boutons d'action #
// event open : ancrer le toaster une fois pour toutes ; les retours arrivent seuls
inv_toaster.ipo_owner = this
// Proposer deux actions ; timeout 0 = le toast attend la decision de l'utilisateur
inv_toaster.of_reset()
// Titre, texte et deux boutons, puis afficher
inv_toaster.is_title = "Mise a jour disponible"
inv_toaster.is_text = "La version 2.0 est prete a etre installee."
inv_toaster.il_timeout = 0
inv_toaster.of_add_button(/*key*/ "install", /*label*/ "Installer")
inv_toaster.of_add_button(/*key*/ "later", /*label*/ "Plus tard")
inv_toaster.of_show()
// event ue_toast_action de inv_toaster : (long al_id, string as_key, string as_action)
choose case as_action
case "install" ; of_start_update()
case "later" ; of_remind_later()
end choose
Réagir au clic sur le message #
// event ue_toast_clicked de inv_toaster : (long al_id, string as_key)
// L'utilisateur a clique le corps du toast : ouvrir l'ecran concerne
Open(w_import_log)
Savoir pourquoi un toast s'est fermé, tout fermer #
// event ue_toast_dismissed de inv_toaster : (long al_id, string as_key, string as_reason)
// Seul un toast ferme par l'utilisateur veut dire pas maintenant : le rappeler plus tard
if as_reason = n_pbt_toaster.REASON_USER then of_remind_later()
// Un nouvel import commence : les notifications du precedent s'en vont
inv_toaster.of_close_all()
Notifier depuis un traitement long #
// Variables locales
long ll_rows, ll_errors
// Lignes chargees et erreurs rencontrees par l'import
ll_rows = of_rows_loaded()
ll_errors = of_errors_met()
// Fin d'un import : informer sans bloquer l'ecran de saisie
inv_toaster.of_reset()
// Le type et le texte suivent le resultat
if ll_errors = 0 then
inv_toaster.is_kind = inv_toaster.KIND_SUCCESS
inv_toaster.is_text = "Import termine : [b]" + String(ll_rows) + " lignes[/b] integrees."
else
inv_toaster.is_kind = inv_toaster.KIND_ERROR
inv_toaster.il_timeout = 0 // une erreur doit etre lue
inv_toaster.is_text = "Import interrompu : " + String(ll_errors) + " erreurs."
end if
// Afficher le toast
inv_toaster.of_show()
Bonnes pratiques #
- Un toaster par fenêtre, posé sur la fenêtre ou tenu par une variable d'instance d'un descendant (voir « Où écrire les événements »), plutôt qu'une création/destruction à chaque message : l'ancrage
ipo_ownerreste en place et les retours arrivent. Un toaster détruit ne reçoit plus rien : ses toasts persistants et ceux à boutons se ferment avec lui, les autres finissent seuls, muets. - Appelez
of_reset()avant chaque notification : sans cela le titre, l'image ou les boutons de la précédente restent posés. - Réservez
il_timeout = 0aux messages qui exigent une décision (erreur bloquante, action proposée) : un toast qui ne part pas tout seul finit par agacer. - Utilisez
ib_screen = trueuniquement pour ce qui doit rester visible quand l'application est en arrière-plan (fin de traitement long, tâche de nuit). - Un toast est un message transitoire : s'il faut absolument une réponse avant de continuer, utilisez messagebox, qui bloque et renvoie le choix.
- Pour un statut permanent plutôt qu'une notification, préférez statusbar.