6. Fonctions transverses #
← Langue et RTL · Sommaire · FAQ →
Ce chapitre regroupe les services disponibles quel que soit le composant : info-bulles, hébergement de contrôles PowerBuilder, glisser-déposer depuis l'Explorateur, focus clavier, export image, et les objets utilitaires non visuels.
6.1 Info-bulles simples et enrichies #
Info-bulle du composant #
uo_bouton.is_tooltip = "Enregistrer le dossier (Ctrl+S)"
Le texte accepte le balisage riche : [b], [br], [color=…], [picture=…]…
Super info-bulle (titre + texte + image) #
Pour une aide contextuelle façon ruban Office :
uo_bouton.is_super_tooltip_title = "Enregistrer"
uo_bouton.is_super_tooltip_text = "Écrit les modifications sur le serveur." &
+ "[br][br][size-=15]Raccourci : Ctrl+S[/size-=15]"
uo_bouton.is_super_tooltip_image = "img\help_save.png"
Les trois propriétés sont indépendantes : un titre seul, ou un titre + texte sans image, sont valides. Dès qu'une propriété is_super_tooltip_* est posée, elle prend le pas sur is_tooltip.
Info-bulle d'un item #
Toute classe d'item (n_pbt_item et ses descendants) porte les quatre mêmes propriétés :
uo_toolbar.of_bar("main").of_item("save").is_tooltip = "Enregistrer"
uo_tab.of_item("clients").is_super_tooltip_title = "Clients"
uo_tab.of_item("clients").is_super_tooltip_text = "128 fiches, dernière synchro à 09:12"
Comportement #
- L'info-bulle est une fenêtre native thémée, identique dans tous les composants (elle n'est pas limitée par les frontières du webview).
- Elle ne s'affiche pas si votre application n'a pas le focus : passer la souris au-dessus d'une fenêtre en arrière-plan ne déclenche rien.
- Elle disparaît quand vous basculez sur une autre application, et au plus tard au bout de 10 secondes.
of_reset()supprime les info-bulles posées sur l'instance et sur ses items.
6.2 Héberger de vrais contrôles PowerBuilder #
Les composants conteneurs n'affichent pas du HTML à la place de vos écrans : ils accueillent de vrais contrôles PowerBuilder (userobjects, DataWindows, groupes de contrôles), reparentés comme fenêtres Win32 enfants. Vos écrans existants sont réutilisés tels quels.
// Onglets : chaque page est un userobject PB
uo_tab.of_add_page("clients", "Clients", uo_page_clients)
uo_tab.of_add_page("factures", "Factures", uo_page_factures, /*fermable*/ true)
// Panneaux dockables : idem
uo_dock.is_main = "doc" // zone centrale
uo_dock.of_add_panel("doc", uo_dock.POSITION_STACK, "", 0, "Document", uo_editeur)
uo_dock.of_add_panel("explorer", uo_dock.POSITION_START, "", 240, "Explorateur", uo_arbre)
uo_dock.of_add_panel("props", uo_dock.POSITION_END, "", 260, "Propriétés", uo_props)
Ce qui est pris en charge pour vous :
- le positionnement et le redimensionnement du contrôle hébergé quand l'onglet ou le panneau change de taille ;
- l'affichage / masquage au changement d'onglet ou de panneau actif ;
- les panneaux flottants, dockés ou masqués automatiquement (dockcontainer) ;
- la destruction propre à la fermeture de la fenêtre.
⚠️ Un contrôle hébergé est une fenêtre native : il se dessine au-dessus de la couche web. C'est voulu (votre DataWindow reste nette et rapide), mais cela signifie qu'aucun effet web — ombre, transparence, animation — ne peut passer par-dessus lui.
6.3 Recevoir des fichiers depuis l'Explorateur Windows #
Un composant peut devenir cible de dépôt pour des fichiers glissés depuis l'Explorateur. La bibliothèque installe une cible de dépôt native : vous recevez les chemins complets, ce qu'un dépôt HTML ne permet pas.
uo_editeur.ib_allow_drop = true
// event ue_drop_files de uo_editeur : (string as_files[])
long ll_i
for ll_i = 1 to UpperBound(as_files)
of_ouvrir_fichier(as_files[ll_i])
next
| Event | Déclenché quand |
|---|---|
ue_drag_enter ( ) | Un glisser de fichiers entre dans le composant |
ue_drag_leave ( ) | Il en sort sans déposer |
ue_drop_files (string as_files[]) | Les fichiers sont déposés — chemins complets |
Le composant fournit lui-même le retour visuel de survol (surbrillance de la zone de dépôt). Publié par les composants où le dépôt a du sens : statictext, codeeditor.
6.4 Clavier et focus #
Un composant PBToolboxAI participe à la navigation clavier de votre fenêtre comme un contrôle natif :
- la touche Tab l'atteint dans l'ordre de tabulation de la fenêtre ;
- les touches (flèches, Entrée, Échap, saisie) sont traitées par le composant qui a le focus ;
- les raccourcis de fenêtre (Entrée = bouton par défaut, Échap = annuler) continuent de fonctionner même quand le focus est dans un composant.
Pour donner explicitement le focus au contenu d'un composant (par exemple après avoir ouvert un panneau de recherche) :
uo_editeur.of_focus_webview()
6.5 Exporter le rendu en image #
Rappel du socle commun : tout composant s'exporte tel qu'affiché.
uo_pivot.of_save_as_png("C:\temp\tableau.png")
uo_pivot.of_save_as_jpg("C:\temp\tableau.jpg")
Utile pour joindre un graphique à un e-mail, alimenter un état, ou tracer un incident utilisateur.
6.6 Boîtes de dialogue et notifications #
Deux services sans contrôle à poser dans la fenêtre :
// Boite de dialogue modale themee (retour synchrone)
n_pbt_messagebox lnv_mb
lnv_mb = create n_pbt_messagebox
lnv_mb.is_title = "Suppression"
lnv_mb.is_message = "Supprimer définitivement [b]12 dossiers[/b] ?"
lnv_mb.is_icon = lnv_mb.ICON_QUESTION
lnv_mb.of_add_button("Supprimer", /*par defaut*/ false, /*annulation*/ false)
lnv_mb.of_add_button("Annuler", /*par defaut*/ true, /*annulation*/ true)
if lnv_mb.of_show(Handle(this)) = 1 then of_supprimer()
destroy lnv_mb
// Notification "toast" en coin d'ecran, non bloquante
n_pbt_toaster lnv_toast
lnv_toast = create n_pbt_toaster
lnv_toast.is_title = "Import terminé"
lnv_toast.is_text = "1 240 lignes intégrées."
lnv_toast.is_kind = lnv_toast.KIND_SUCCESS
lnv_toast.of_show()
destroy lnv_toast
Détails complets : messagebox et toaster.
6.7 Objets utilitaires non visuels #
Livrés dans la même PBL, sans webview ni rendu : ce sont de simples enveloppes autour de la DLL. Créez-les, utilisez-les, détruisez-les.
Encodage Base64 — u_pbt_base64 #
u_pbt_base64 lnv_b64
string ls_encode
lnv_b64 = create u_pbt_base64
ls_encode = lnv_b64.of_encode("Bonjour") // texte -> UTF-8 -> Base64
ls_texte = lnv_b64.of_decode(ls_encode) // "" si l'entree est invalide
destroy lnv_b64
Empreintes — u_pbt_hash #
u_pbt_hash lnv_hash
lnv_hash = create u_pbt_hash
ls_empreinte = lnv_hash.of_sha256("mot de passe") // hexa minuscule
ls_fichier = lnv_hash.of_file("SHA256", "C:\livraison.zip")
destroy lnv_hash
| Méthode | Rôle |
|---|---|
of_string (string as_algo, string as_texte) | Empreinte d'une chaîne — MD5, SHA1, SHA256, SHA384, SHA512 |
of_file (string as_algo, string as_chemin) | Empreinte du contenu d'un fichier ("" si illisible) |
of_md5 · of_sha1 · of_sha256 · of_sha512 | Raccourcis |
Expressions régulières — u_pbt_regex #
Syntaxe ECMAScript, absente de PowerScript.
u_pbt_regex lnv_re
string ls_trouves[]
lnv_re = create u_pbt_regex
if lnv_re.of_is_match("^[\w.]+@[\w.]+\.\w{2,}$", ls_email) then …
ls_annee = lnv_re.of_match("(\d{4})-(\d{2})-(\d{2})", ls_date, /*groupe*/ 1)
ls_propre = lnv_re.of_replace("\s+", ls_saisie, " ")
ll_nb = lnv_re.of_match_all("[A-Z]{2}\d{6}", ls_texte, ls_trouves)
destroy lnv_re
| Méthode | Rôle |
|---|---|
of_is_match (motif, texte [, ab_ignore_case | al_flags]) | Le texte correspond-il ? |
of_match (motif, texte, ai_groupe [, al_flags]) | Première correspondance (0 = tout, 1.. = groupe capturant) |
of_match_all (motif, texte [, ai_groupe, al_flags], ref as_res[]) | Toutes les correspondances ; renvoie le nombre |
of_replace (motif, texte, remplacement) | Remplace toutes les occurrences ($1… autorisés) |
Options combinables : FLAG_IGNORE_CASE (1), FLAG_SINGLELINE (2, le . traverse les sauts de ligne).
Identifiants uniques — u_pbt_guid #
u_pbt_guid lnv_guid
lnv_guid = create u_pbt_guid
ls_id = lnv_guid.of_new() // 1b4e28ba-2fa1-11d2-883f-0016d3cca427
ls_id = lnv_guid.of_new_braces() // {1b4e28ba-...}
ls_id = lnv_guid.of_new_plain() // 1b4e28ba2fa111d2883f0016d3cca427
destroy lnv_guid
Archives ZIP — u_pbt_zip #
u_pbt_zip lnv_zip
lnv_zip = create u_pbt_zip
lnv_zip.of_compress("C:\temp\livraison.zip", "C:\appli\export") // fichier OU dossier
lnv_zip.of_extract("C:\temp\livraison.zip", "C:\appli\import") // dossier cree si absent
destroy lnv_zip
Les deux méthodes renvoient un boolean.
6.8 Informations sur la bibliothèque #
// Version de la DLL
string ls_version
ls_version = Space(32)
PBT_GetVersion(ls_version, 32)
| Fonction globale | Rôle |
|---|---|
PBT_GetVersion (ref string, long) | Version de la bibliothèque |
PBT_CheckRuntime (ref string, long) | Version du runtime WebView2 installé (≤ 0 = absent) |
PBT_GetLastErrorMessage (ref string, long) | Dernier message d'erreur du processus |
PBT_LicenseStatus ( ) | État de la licence — voir Licence |
6.9 Imprimer #
Tout composant sait s'imprimer, tel qu'affiché, sans DataWindow intermédiaire.
// Silencieux : un PDF sur disque, rien à cliquer
uo_grille.of_print_to_pdf("C:\etats\ventes.pdf")
// Paysage, pour une grille large
uo_grille.of_print_to_pdf(/*fichier*/ "C:\etats\ventes.pdf", /*paysage*/ true)
// Avec dialogue : l'utilisateur choisit son imprimante et voit l'aperçu
uo_grille.of_print()
// Directement le dialogue système d'impression
uo_grille.of_print(/*dialogue systeme*/ true)
| Méthode | Rôle |
|---|---|
of_print_to_pdf (string as_path) · of_print_to_pdf (string, boolean ab_paysage) | Écrit un PDF sans rien afficher. Ne rend la main qu'une fois le fichier écrit (0 = fait) |
of_print ( ) · of_print (boolean ab_dialogue_systeme) | Ouvre le dialogue d'impression. Rend la main dès que le dialogue est ouvert : ce que l'utilisateur en fait ensuite lui appartient |
⚠️ Ce qui est imprimé est ce qui est RENDU. Une grille virtualisée n'imprime que les lignes qu'elle détient : pour un état complet, passez d'abord par une mise en page qui les affiche toutes (pagination), ou exportez les données plutôt que le rendu.
Le code retour -6 signale un runtime WebView2 trop ancien pour imprimer (1.0.1108 pour le PDF, 1.0.1587 pour le dialogue). Tout le reste suit les codes retour communs.