PBToolboxAI v5 ← Site

12. Migrer de la 4.0 à la 5.0 #

← Migrer de la 3.0 à la 4.0 · Sommaire · Notes de version →


La 5.0 ne change aucune signature des trente-sept composants de la 4.0, ni aucun événement — sauf la barre de boutons (buttonbar, 12.7) et l'événement ue_link_clicked du visualiseur Markdown (markdownview), qui reçoit un second argument, as_kind (12.5). Trois composants changent de mots. La barre de progression (progressbar) prend ceux des jauges — ib_label, il_color et is_label_format disparaissent au profit de ib_show_value, il_value_color, is_format et is_unit (12.1). Le graphique cartésien (chartcartesian) écrit ses nombres par is_format, comme les jauges et le camembert : of_set_value_format et of_clear_value_format disparaissent, et ii_point_count d’une série devient il_point_count (12.4). Le croisé (crosstab) suit le même chemin : of_set_value_format et of_clear_value_format disparaissent au profit de is_format — sur le champ, ou sur une seule valeur par of_value — et de ib_negative_red (12.8). Le compilateur vous montre chaque ligne à reprendre. La barre latérale (listbar) change un événement : ue_item_rclicked reçoit en plus le point d'écran du clic, al_x et al_y (12.9). Le panneau de tuiles (tilesbox) renomme un événement : ue_tile_context(as_keys) devient ue_tile_rclicked(as_keys, al_x, al_y), et la position d'of_move_tile et d'of_insert_tile passe en long al_position (12.12). Le menu radial (radialmenu) perd quatre propriétés d'infobulle qu'il n'a jamais montrées — is_tooltip, is_super_tooltip_title, is_super_tooltip_text et is_super_tooltip_image (12.5). Le calendrier (scheduler) change trois événements de geste : ue_appointment_changing reçoit as_kind, ue_appointment_moved et ue_appointment_resized reçoivent les valeurs d'avant (12.10). L'explorateur du shell (shellexplorer) change un événement : ue_error reçoit en plus le chemin et une raison constante, as_path et as_reason (12.11). Le bloc de texte riche (statictext) change un événement : ue_hyperlink reçoit en plus ab_opened, si le lien s'est vraiment ouvert (12.5). L'onglet (tab) change un événement : ue_tab_rclicked reçoit en plus le point d'écran du clic, al_x et al_y (12.13). Le lecteur de sons (soundplayer) change trois événements : ue_started, ue_ended et ue_failed reçoivent en plus le numéro du son, al_sound (12.14). Le toaster (toaster) change un événement : ue_toast_dismissed reçoit en plus la raison de la fermeture, as_reason (12.15). Le navigateur web (webbrowser) : of_go_back, of_go_forward et of_stop rendent un long, et sous ib_veto_navigation une adresse tapée par l'utilisateur est demandée à ue_navigating (12.17). La barre d'outils (toolbar) change un événement : ue_item_rclicked reçoit en plus le point d'écran du clic, al_x et al_y (12.18). Le lecteur vidéo (video) change une signature : of_stop devient une fonction qui rend un long (12.16) — un appel écrit comme une instruction compile toujours. Trois composants changent un événement de clic droit d'item, qui reçoit en plus son point d'écran al_x, al_y : la barre de boutons (ue_button_rclicked), le fil d'Ariane (breadcrumb, ue_item_rclicked) et le graphique cartésien (ue_point_rclicked) ; la barre d'état (statusbar) donne ce point comme les autres, sans plus le multiplier par l'échelle de l'écran (12.19). Le socle (12.20) : la raison d'un échec d'un composant non visuel se lit par of_get_last_error() — la propriété is_last_error disparaît de crypto, restclient, soundplayer, speechout, xml, u_pbt_regex et u_pbt_zip —, et of_stop, of_close et of_reset des non visuels rendent un long.

Le reste ne demande rien à votre code : la grille de données (datagrid) et le ruban (ribbon) gagnent des masques de saisie numériques, et l'éditeur d'une colonne numérique de la grille s'ouvre désormais sur le texte du masque (12.2, 12.3). Les nouveaux composants de la 5.0 sont présentés dans les notes de version.

12.1 progressbar : les mots des jauges #

La 5.0 apporte deux jauges, linéaire (gauge) et à cadran (angulargauge). Une barre de progression montre elle aussi une valeur sur une échelle : la bibliothèque ne parle plus qu'une langue pour cela, et la barre, qui disait autrement la même chose, prend les mots des jauges. Aucun ancien nom ne survit : ni propriété, ni nom accepté par of_set_property.

Quoi4.05.0
Afficher la lectureuo.ib_label = trueuo.ib_show_value = true
Couleur de la valeur (-1 = le thème, inchangé)uo.il_color = RGB(…)uo.il_value_color = RGB(…)
Une lecture qui écrit la valeuruo.is_label_format = "{value} of {max} rows"uo.is_format = "#,##0" + uo.is_unit = "of 500 rows"
Le pourcentage (défaut, inchangé)uo.is_label_format = ""uo.is_format = ""
Piloter par nomof_set_property("label", …), ("label_format", …), ("color", …)("show_value", …), ("format", …), ("unit", …), ("value_color", …)
// 4.0 : the label wrote the value through placeholders
uo_progress.ib_label        = true
uo_progress.il_color        = RGB(/*red*/ 0, /*green*/ 120, /*blue*/ 215)
uo_progress.is_label_format = "{value} of {max} rows"
// 5.0 : the words of the gauges - a display format for the value, then a unit
uo_progress.ib_show_value  = true
uo_progress.il_value_color = RGB(/*red*/ 0, /*green*/ 120, /*blue*/ 215)
uo_progress.is_format      = "#,##0"
uo_progress.is_unit        = "of 500 rows"

La recette : compilez ; chaque ib_label, il_color et is_label_format d'une barre de progression est signalé. Remplacez les deux premiers par ib_show_value et il_value_color. Pour le troisième : un texte vide reste vide dans is_format ; un libellé qui écrivait la valeur devient un format ("#,##0") et une unité ; un libellé qui écrivait le pourcentage garde is_format vide et met son texte dans is_unit. Un of_set_property qui nommait label, label_format ou color rend désormais -5 et ne fait rien (of_get_last_error nomme la propriété) : cherchez ces noms dans votre code.

12.2 datagrid : un éditeur numérique qui tape au masque #

Aucune signature ne change, et ue_cell_edited reçoit toujours le nombre nu (1234.5). Ce qui change se voit à l'écran : la saisie d'une colonne numérique suit désormais un masque de saisie, dans la syntaxe du DataWindow — celui que vous donnez par la nouvelle propriété is_mask de la colonne, sinon son format d'affichage dépouillé de ses littéraux.

Quoi4.05.0
L'éditeur d'une cellule affichée $1,234.50s'ouvrait sur le nombre nu 1234.5 ; tout caractère était acceptés'ouvre sur 1,234.50 ; le groupement apparaît au fil des chiffres, les décimales sont bornées au masque, les lettres refusées ; un nombre collé est lu dans la langue d'affichage
Un nombre de quatre chiffres sous un format numériquenon groupé dans certaines langues (1234 en espagnol)groupé dans toutes les langues (1.234 en espagnol)
Un négatif arrondi à zéro-00
Ouvrir puis fermer l'éditeur sans rien taperpouvait changer une valeur que le format arronditne change rien
Une cellule de notation (rating) lue par un lecteur d'écrancinq signes étoile4 / 5
// 5.0 : the input mask of a numeric column - the cell still receives the bare number
uo_grid.of_column(/*key*/ "revenue").is_mask = "#,##0.00"

La recette : rien à changer. Un code qui lisait le texte tapé ne le voit pas : ue_cell_edited rend toujours le nombre. Une colonne dont la saisie doit rester libre (un code, un numéro de pièce) est une colonne texte, pas numérique.

12.3 ribbon : les masques d'un compteur #

Rien ne change pour un compteur qui n'a pas de masque. Deux propriétés nouvelles de sa poignée, dans la syntaxe de PowerBuilder : is_mask, le masque de saisie ("#,##0.00", "0%"), et is_format, le format d'affichage avec ses littéraux (0 "pt" montre 11 pt, qui se tape 11). id_value et ue_value_changed gardent le nombre nu, la bascule entre les deux ne lève aucun événement, et les masques suivent le compteur dans le panneau d'un groupe replié.

// 5.0 : a font size shown "11 pt", typed "11"
uo_ribbon.of_item(/*keys*/ "home/font/size").is_format = "0 ~"pt~""

La recette : rien à changer.

12.4 chartcartesian : le format des nombres par is_format #

Le graphique cartésien écrivait ses nombres par une fonction à quatre arguments (décimales, préfixe, suffixe, séparateur de milliers). La 5.0 range les graphiques et les jauges sous une seule langue : un format d'affichage PowerBuilder, celui d'une colonne de DataWindow, dans la propriété is_format — du graphique entier, et d'un axe par sa poignée. Les sections positif;négatif;zéro, les littéraux et le pourcentage viennent avec, et les séparateurs restent ceux de la langue d'affichage. Aucun ancien nom ne survit.

Quoi4.05.0
Le format du graphiqueuo.of_set_value_format(0, "$", "", true)uo.is_format = "$#,##0"
Le format d'un axeuo.of_set_value_format(AXIS_VALUE2, 1, "", " u", false)uo.of_axis(AXIS_VALUE2).is_format = '0.0" u"'
Revenir au nombre tel queluo.of_clear_value_format()uo.is_format = "" (et "" sur chaque axe qui a le sien)
Piloter par nom—of_set_property("format", "#,##0")
Le nombre de points d'une série (lecture seule)uo.of_item("k").ii_point_count (integer)uo.of_item("k").il_point_count (long)
// 4.0 : decimals, prefix, suffix and thousands as four arguments
uo_chart.of_set_value_format(/*decimals*/ 0, /*prefix*/ "$", /*suffix*/ "K", /*thousands*/ true)
uo_chart.of_set_value_format(/*axis*/ u_pbt_chartcartesian.AXIS_VALUE2, /*decimals*/ 1, /*prefix*/ "", /*suffix*/ " u", /*thousands*/ false)
// 5.0 : a display format, written as in a DataWindow - for the chart, then for one axis
uo_chart.is_format = "$#,##0K"
uo_chart.of_axis(/*axis*/ u_pbt_chartcartesian.AXIS_VALUE2).is_format = '0.0" u"'

La recette : compilez ; chaque of_set_value_format et of_clear_value_format est signalé. Écrivez le format comme dans une DataWindow : decimals donne le nombre de 0 après le point (-1 = #,##0.###), thousands le , du groupement, le préfixe et le suffixe s'écrivent devant et derrière (entre guillemets s'ils contiennent des chiffres ou des espaces). Le format d'un axe va dans of_axis(<axe>).is_format.

12.5 Autres comportements que vous pouvez voir #

Quoi4.05.0
Menus natifs d'un composant qui a son propre accent (il_theme_accent)l'accent ne se voyait que dans la case d'une entrée cochéel'entrée pointée le montre aussi, par un liseré au bord de départ (à droite en RTL)
button : Ctrl, Alt ou Maj + Entrée (et Ctrl / Alt + Espace, Ctrl + Échap) sur le bouton qui a le focuscliquaient ce boutonvont à la fenêtre, comme depuis tout autre contrôle : le raccourci d'un autre bouton (is_shortcut = "Ctrl+Enter") part, le bouton focalisé non ; Entrée et Espace seuls le cliquent toujours
button grisé ib_default (ou ib_cancel), le plus proche du focus, dans une feuille MDIEntrée (Échap) partait au bouton par défaut d'une autre feuillela touche reste dans sa feuille : le champ, ou le CommandButton PB par défaut, la reçoit
breadcrumb : ii_max_visible poséun nombre exact de segments en OVERFLOW_COLLAPSE (la largeur ne repliait plus rien), ignoré en OVERFLOW_SCROLL et OVERFLOW_SHRINKun plafond dans les trois modes ; en OVERFLOW_COLLAPSE la largeur replie encore davantage quand la barre est trop étroite, et le lieu courant ne sort plus de la barre
breadcrumb : of_add_child avec un texte videune ligne vide dans le menula clé de la branche, comme of_add_children
breadcrumb : Ctrl+S, F5 et les autres raccourcis de la fenêtre pendant la saisie du cheminne partaient paspartent, comme depuis un SingleLineEdit ; Entrée et Échap restent au champ
breadcrumb : ue_children_needed qui ne rend jamais la mainplus aucun chevron ne s'ouvrait jusqu'au prochain of_resetun clic sur un autre chevron abandonne la question, et le fil la laisse tomber au bout de 10 secondes
chartcartesian : une bande ou un seuil sans couleur (-1 ou NULL)un bloc plein de la couleur du texteun lavis pâle de l'accent du thème (la ligne d'un seuil : l'accent) ; une borne NULL est refusée (-5)
chartcartesian : un poids NULL dans une carte de chaleurla case peinte de la couleur la plus chaude, étiquetée « NaN »une case vide : rien n'y est dessiné, étiqueté ni cliquable ; une bulle sans poids garde la taille par défaut, hors de l'échelle
chartcartesian : of_remove_seriesles séries suivantes changeaient de couleur ; l'info-bulle de la série retirée habillait la prochaine série de même cléchaque série garde la couleur prise à son ajout ; l'info-bulle et les couleurs d'item partent avec la série
chartcartesian : of_append_values / of_append_categories avec ib_animatedtout le graphique retombait sur l'axe et remontait à chaque ajout, tant que la fenêtre n'était pas pleineseule la forme ajoutée monte, les autres glissent ; l'arrivée entière ne se rejoue qu'à l'ajout d'une série
chartcartesian : barres empilées sur les deux axes de valeursles deux piles se superposaientcôte à côte dans la catégorie
chartcartesian : une balise dans une catégorie ou un libellé de valeurécrite telle quelle sur l'axe, interprétée dans le panneaudu texte partout : la balise est retirée (l'axe, le panneau, #x#, #label#)
chartcartesian : Échap sans rien d'ouvert, Entrée sur un trougardés par le graphiquevont à la fenêtre : son bouton Annuler, son bouton par défaut
codeeditor : Ctrl+Tab ou Alt+Tab dans l'éditeurindentaient le code : le clavier ne sortait plus de l'éditeurvont à la fenêtre (la page suivante d'un onglet) ; Échap puis Tab sort de l'éditeur, Ctrl+M ou ib_tab_moves_focus font sortir Tab
codeeditor : of_find sur une expression régulière invaliderendait 0rend -5, comme of_replace
codeeditor : un nouvel is_text pendant une recherchela barre restait ouverte et levait ue_find_resultla barre se ferme, sans rien lever (une valeur est muette)
codeeditor : is_syntax = "SQL" relu"sql""SQL", tel qu'écrit
codeeditor replié : #regionopen, la copie et of_selected_textaffiché #region ; la copie rendait l'affichage, sans les lignes des régions ferméesaffiché tel qu'écrit ; la copie et of_selected_text rendent la source de la plage, régions fermées comprises
codeeditor : marqueurs et il_doc_line quand des lignes sont ajoutées ou retirées au-dessusrestaient sur le même numéro de lignesuivent leur ligne ; une ligne supprimée emporte ses marqueurs
codeeditor : le curseur après « Tout remplacer » (of_replace_all)sur le dernier remplacementreste où il était, décalé de ce qui a été inséré avant lui
codeeditor : Ctrl+Z, Ctrl+Yl'historique du navigateur, perdu quand le texte était écrit focus ailleursl'historique du composant (of_undo, of_redo) : il compte aussi ce que fait votre code, un nouvel is_text le vide
crypto : of_totp_verify(secret, code, ref al_step) d'un code tapé avec des espaces (« 864 010 »)refusé, pas 0accepté, comme par la forme à deux arguments ; les espaces sont ignorés
crypto : of_base64_encode_file d'un fichier de 32 à 64 Mo dans une application 32 bitspromis jusqu'à 64 Mo ; la mémoire du processus pouvait manquer"" et of_get_last_error() (32 Mo au plus en 32 bits) ; of_base64_encode_file_to_file encode un fichier de toute taille dans un autre fichier
crypto : of_totp_uri d'un secret tapé à la main (« gezd gnbv », un « 0 »)écrit tel quel dans l'URIécrit en base32 majuscule, sans espaces ni = ; un autre caractère : "" et of_get_last_error()
crypto : un argument NULLis_last_error pouvait revenir NULLcompte pour un argument vide ; of_get_last_error() n'est jamais NULL
crypto : une cible \x ou C:x (of_base64_decode_to_file, of_encrypt_file, of_decrypt_file)-5 et un message faux (« not a base64 value », « all needed »)-5, et of_get_last_error() dit que le chemin dépend du dossier courant d'un lecteur
commandpalette : une recherche et les commandes récentes (is_recent)une commande récente gagnait jusqu'à il_max_recent × 4 points : avec une grande limite, elle passait devant une meilleure correspondanceelle ne fait que départager des résultats qui correspondent à peu près aussi bien
commandpalette : une commande sans groupe (as_group = "") déclarée entre deux groupesrangé sous l'en-tête du groupe déclaré avant luien tête de la liste, sans en-tête
commandpalette : Début / Fin dans le champ qui contient du texte, Maj+Débutdéplaçaient la sélection dans la liste ; Maj+Début ne sélectionnait riendéplacent le curseur dans le champ ; Ctrl+Début / Ctrl+Fin vont à la liste ; Maj sélectionne dans le champ
commandpalette : un clic droit ou du milieu sur une lignelançait la commandene fait rien
commandpalette : of_command sur une clé qu'aucune commande ne porteib_enabled / ib_visible se relisaient true, une écriture se perdait en silenceils se relisent false ; une écriture est perdue et of_get_last_error le dit
commandpalette : un second objet palette qui avait repris un accord est détruitla touche ne répondait plus à personne jusqu'à ce que le premier la reposel'accord revient au premier
commandpalette : is_recent avec des espaces ou des clés répétées, il_max_recent abaissé"a, b" ne gardait que a ; un doublon s'affichait deux fois ; is_recent restait longnettoyé, coupé à la limite et rendu propre à is_recent à l'ouverture
dockcontainer : construire le dock, restaurer une dispositionue_layout_changed à chaque ajout, le premier ne connaissant qu'un panneau : une disposition enregistrée dans l'événement était écrasée par une disposition à moitié construiteune fois pour une rafale encadrée par of_set_redraw(false) … (true), à la reprise (et pour des changements à moins de 40 ms) ; of_set_layout le lève une fois. Lisez le réglage enregistré avant de créer les panneaux
dockcontainer : le panneau au premier plan d'une pile change sans clic sur son ongletrien n'était levé (un panneau empilé par of_add_panel ou of_move_panel, celui de devant fermé, détaché ou retiré, un panneau raccroché)ue_panel_selected du panneau passé devant, après ue_panel_closed, ue_panel_floated ou ue_panel_docked ; une disposition restaurée n'en lève pas. n_pbt_dock_panel.ib_front le relit
dockcontainer : ib_visible = true sur un panneau fermé d'une pileil revenait derrière l'onglet actifil passe devant, et ue_panel_selected suit ; dans un groupe replié il reste sur le rail
dockcontainer : of_move_panel vers le panneau lui-même (as_target = as_key)rendait 0 sans rien faire, ou scindait sa pilerend -5 ; pour scinder une pile, visez un autre panneau de la pile (of_move_panel("b", "a", POSITION_BOTTOM))
dockcontainer : un panneau déplacé dans un groupe replié, ou hors de luiib_pinned changeait sans événementue_panel_pinned suit
dockcontainer : un clic sans déplacement sur un séparateurlevait ue_layout_changedne lève rien : rien n'a changé
dockcontainer : of_keys_at avec des clés numériquesles clés entières d'abord (2, 10, zeta)l'ordre d'ajout (zeta, 10, 2)
dockcontainer détruit à l'exécution (CloseUserObject)ses contrôles revenaient sur la fenêtre, masquésils retrouvent la visibilité qu'ils avaient avant of_add_panel
dockcontainer : of_add_panel d'un contrôle qui CONTIENT le dockles fenêtres se bouclaientrend -5, le contrôle reste où il était
crosstab : AGG_COUNTcomptait les lignescompte les valeurs non vides, comme le Nombre d'Excel ; AGG_COUNT_ROWS, nouveau, compte les lignes
crosstab : une somme sans aucune valeur ; une « différence avec la précédente » à côté d'une cellule vide0une cellule vide (of_get_cell_value rend NULL)
crosstab : Top N ou Bottom N (of_set_value_filter, ou le menu) sur un champ placé sous un autre de sa zoneclassés sur tout le tableauclassés à l'intérieur de chaque parent (la meilleure ville de chaque région) ; au premier niveau, inchangé ; les ex-aequo du N-ième restent tous
crosstab : aucun champ en Colonnesune colonne de total qui doublait la colonne unique (`Nord650650`)plus de colonne de total ; ib_col_grand_total garde sa valeur
crosstab : plusieurs mesures et des champs en Colonnesune colonne Total par mesure, sans nom de mesure, et qui ne se triait pasun en-tête « Total » puis un en-tête par mesure, triable
crosstab : ue_layout_changedlevé par les gestes de l'utilisateur, et par is_thousands et of_remove_field seulementlevé aussi par tout ordre du code qui change ce que rend of_get_layout (of_set_layout compris), une fois par ordre ; une seule fois à la fin d'une construction encadrée par of_set_redraw(false) … (true) ; jamais si rien ne change, ni pour of_reset
crosstab : un pourcentage (SHOW_PCT_*)57.9 % dans toutes les languesécrit comme la langue d'affichage l'écrit : 57.9% en anglais, 57,9 % en français
crosstab : le filtre de libelléproposé par le menu de la puce d'un champ numérique seulement ; sur une date, of_set_label_filter comparait l'année (2025-03-15 valait 2025)proposé pour tout champ ; sur une date, la surcharge texte prend des jours : LABEL_BEFORE, LABEL_AFTER, LABEL_BETWEEN ("yyyy-mm-dd", jours compris) ; la surcharge numérique, ou LABEL_CONTAINS / LABEL_BEGINS / LABEL_ENDS, sur une date : -5
crosstab : of_group_date_field sur un champ qui ne contient pas de dates0, et un seul membre « (vide) »-5
crosstab : of_add_calc_field / of_add_calc_measure refusés par la grille (nom déjà pris, formule qui ne se compile pas)0 ; seul ue_calc_field_error le disait-5 et la raison dans of_get_last_error (ue_calc_field_error est toujours levé) ; un nom qui contient / ou ` : -5 ; une formule accepte .5 et 1e3`
crosstab : of_set_value_filter Top ou Bottom de moins de 1 membre ; of_expand_to_level sous 1ramenés à 1-5
crosstab : of_get_cell_value appelé depuis un événement levé pendant un ordre de ce script-2, comme un composant non créé-4, et of_get_last_error dit pourquoi : lisez après l'événement
crosstab : le menu Options de la grille (la roue dentée)« Total général » et « Sous-totaux » basculaient les deux axes d'après celui des lignesune entrée par axe : ligne et colonne de total général, sous-totaux des lignes et des colonnes
crosstab : of_from_datastore — une colonne CHAR, un décimal, le Format d'une colonneles blancs de remplissage restaient dans le membre ; le Format était ignoréles blancs de remplissage sont retirés ; un décimal se lit avec le séparateur du poste ; le Format de la colonne est le format par défaut de ses valeurs
datagrid : une ligne sélectionnée que la recherche ou un filtre masque, ou que of_remove_row retirerestait sélectionnée en silence (of_selected_keys et ue_row_menu_clicked la portaient)quitte la sélection, et ue_selection_changed le dit ; of_select_rows ne prend pas une ligne masquée
datagrid : ib_hidden, is_pin, ii_index posés à la valeur qu'ils ont déjà ; un clic sur la poignée sans la tirerlevaient ue_layout_changedne lèvent rien : rien n'a changé
datagrid : des changements de disposition entre of_set_redraw(false) et of_set_redraw(true)un ue_layout_changed par changementun seul, à la reprise, avec la disposition finale
datagrid : un type ou un rendu hors des constantes (of_add_column, is_renderer, is_selection_mode) ; of_add_row_menu_item sans composant crééacceptés et relus tels quels, sans effet ; 0of_add_column rend -5 (of_get_last_error dit lequel) ; un rendu inconnu se relit "", un mode inconnu SELECT_NONE ; -2
datagrid : of_reload_row ou of_update_row d'une cellule modifiéela marque « modifiée » restaitelle part : la ligne tient de nouveau ce que tient le DataStore
datagrid : éditer une colonne à liste de codes, une date ; une colonne time d'un DataStorele <select> et le champ de date du moteur ; une heure était du textela liste et le calendrier de la bibliothèque (une date se TAPE aussi, dans l'ordre de la langue) ; une heure (TYPE_TIME) : tri, filtre > 09:00, format, saisie 9:5
datagrid : un filtre > 3 sur une note sans type ou sur une colonne à codescherchait le texte « > 3 » : aucune lignecompare la donnée (le nombre, le code)
datagrid : arbre sous une recherche ; une ligne dont le parent n'est pas dans la grillel'enfant trouvé restait caché ; la ligne n'apparaissait jamaisses ancêtres sont montrés, ouverts ; la ligne est à la racine
datagrid : of_from_datastore / of_load_rows après of_open_source ; of_append_rows sans clé après of_from_datastore ; une valeur CHARla grille restait en squelettes ; la ligne était refusée (-5) ; gardait son remplissage d'espacesla source est quittée ; la clé suit le plus grand RowID ; rognée
datagrid : of_export_xlsxles dates partaient en texte ; aucun plafondde vraies dates Excel ; un classeur trop lourd (au-delà d'environ 18 Mo) est refusé, ue_xlsx_saved dit pourquoi
messagebox : Échap ou Alt+F4 sur une boîte sans bouton d'annulationfermaient la boîte et rendaient 0 — of_info aussi, qui promettait 1comme Windows : une boîte à un seul bouton se ferme par ce bouton (of_info rend 1), une boîte Oui / Non ne se ferme pas — il faut répondre ; ib_closable = true rend le 0 de la 4.0. Un test = 2 migré d'un MessageBox ne laisse plus passer une suppression
messagebox : un raccourci (of_info, of_error, of_confirm, of_prompt…) après avoir posé il_accent, is_position, ib_movable, une taille ou ib_input_passwordtout était effacé en silence : le mot de passe de of_prompt s'affichait en clairle raccourci ne remplace que le contenu (titre, message, icône, boutons, case, choix) ; l'apparence et les réglages du champ restent. of_reset() efface tout
messagebox : of_reset() après une boîteof_get_last_error, of_checked, of_action et of_input_value parlaient encore de l'ancienne boîteils sont remis à zéro
messagebox : un champ obligatoire rempli d'espacesacceptévide : le bouton par défaut attend (la valeur tapée revient telle quelle)
messagebox : une zone [action] dans le titre, un libellé ou le pied ; un lien dans un choix ; deux boutons au même mnémoniquela zone ne faisait rien ; le lien ouvrait le navigateur ET choisissait ; Alt+lettre répondait par le premier boutonla zone répond comme dans le message (of_action) ; le lien s'ouvre sans choisir ; Alt+lettre passe le focus d'un bouton à l'autre, Entrée choisit
messagebox : Ctrl+Cperdait le & de &&, copiait les balises d'un bouton, ignorait la saisieles libellés tels qu'affichés, « libellé : valeur » du champ (jamais un mot de passe), les détails et le pied de page
messagebox : un descendant qui appelait xx_set_style_override ou xx_clear_style_override (protégées)surchargeait un jeton de thème de la boîteelles ont disparu : il_accent colore la boîte
json et jsontree : un niveau de chemin qui contient ~0 ou ~1lu tel quel ; une clé qui contient / n'avait pas de chemin~1 est un / de la clé, ~0 un ~ (JSON Pointer, RFC 6901) : paths/~1users lit la clé /users ; une clé qui contient un ~ s'écrit ~0 dans un chemin
json : un niveau de chemin vide (a//b, a/) ou un chemin qui commence par /refusé par -5, lu absentun niveau vide est la clé "", un / en tête est la forme complète du pointeur : /name vaut name, / désigne la clé "" de la racine
json : of_get_number, of_get_decimal, of_get_longlong sur une chaîne comme "12 kg" ou "1,5"lisait le début : 12, 10 : une chaîne ne compte que si elle est tout entière un nombre JSON — "12.50" vaut toujours 12,5
json : of_set_members d'une clé que le document porte déjàla clé était écrite une seconde fois : n_pbt_json lisait la première, un navigateur ou un serveur la dernièrela valeur est remplacée en place ; une clé que le fragment répète garde sa dernière valeur
json : of_pretty d'un document qui porte une valeur of_set_raw imbriquée sur plus de 512 niveauxun autre document, coupé à 512 niveauxun texte vide
jsontree : clic sur une clé qui contient /, une clé vide, ou sous une clé en doubleun chemin qui lisait une AUTRE valeur dans n_pbt_jsonx~1y pour la clé x/y, a//b pour une clé vide ; of_selected_addressable rend false sous la seconde de deux clés identiques
jsontree : Ctrl+C avec un morceau de texte surligné à la sourisle nœud entierle morceau surligné
jsontree : un JSON qui commence par un BOMrefusé (ue_error)affiché, comme n_pbt_json le lit ; is_json se relit tel quel
jsontree : le message de ue_error en anglaisInvalid JSON : …Invalid JSON: … (chaque langue garde sa ponctuation) ; 01, 1., 1e disent Bad number
jsontree : of_expand_path pendant une recherchereplié de nouveau au pas suivant de la recherche, sans ue_node_toggledreste ouvert, avec les blocs ouverts au-dessus de lui
jsontree : Espace sur une valeur sélectionnéefaisait défiler l'arbre d'une pagene fait rien (un bloc se plie toujours)
xmltree : un blanc entre deux enfants (<b>x</b> <i>y</i>)n'avait pas de ligne : /p/text()[1] rendait -5une ligne à lui, montrée ␠, avec son chemin : les numéros de ligne d'un contenu mixte changent
xmltree : un texte entre deux enfants (Hello <b>x</b> again)Hello, again : ses blancs de bord rognésHello , again : seuls les retours à la ligne de mise en page partent
xmltree : of_select_path d'un XPath dont le premier nœud est un blanc de mise en page (//text())-5le premier nœud que l'arbre MONTRE est sélectionné
xmltree : of_selected_value d'un élément qui ne contient que des retours à la ligne (affiché <x/>)""ces retours à la ligne, comme n_pbt_xml les lit
xmltree : Ctrl+C avec un morceau de texte surligné à la sourisle XML du nœud entierle morceau surligné
xmltree : le message de ue_error en anglaisInvalid XML : …Invalid XML: … (chaque langue garde sa ponctuation)
xmltree : of_expand_path pendant une recherchereplié de nouveau au pas suivant de la recherche, sans ue_node_toggledreste ouvert, avec les éléments ouverts au-dessus de lui
xmltree : Espace sur une feuille sélectionnéefaisait défiler l'arbre d'une pagene fait rien (un élément à enfants se plie toujours)
jsontree, xmltree : une recherche qui se ferme (Échap dans la boîte, of_clear_search, of_reset, ib_search_enabled = false)aucun événement : une ligne « 3 / 12 » de l'application restait fausseue_search_result(0, 0), une fois ; rien quand aucune recherche ne tournait
PBT_SetDefaultFont avec une taille : codeeditor, jsontree, xmltree, ribbon, toolbar, crosstab, datagrid, tilesbox, stepbar, listbar, dockcontainer, video, picture, les menus et info-bullesle code, le document, le ruban (sa taille de thème) et bien des textes secondaires gardaient leur tailleils suivent la taille de l'application, dans leurs proportions ; la taille de l'application passe devant celle du ruban du thème ; un ii_font_size du codeeditor passe devant les deux
markdownview : ue_link_clicked(string as_url)(string as_url, string as_kind) : un script déjà écrit pour l'événement reste valable ; as_kind (LINK_WEB, LINK_MAIL, LINK_DOCUMENT, LINK_FILE, LINK_OTHER) dit ce qu'est le lien — triez sur lui plutôt que sur le texte de l'adresse
markdownview : une image d'un document posée sur un partage réseauchargéerefusée, sauf si elle est sur le partage d'où le document a été lu, ou avec ib_network_pictures ; un document lu sur le Web n'affiche aucun fichier du poste
markdownview : un nouvel is_markdown du même document, of_refreshla vue remontait en hautla position de lecture est gardée ; un nouvel is_source part toujours du haut
markdownview : of_toc, of_scroll_to et une recherche juste après is_sourceagissaient sur le document précédentle fichier se lit en arrière-plan : of_toc rend 0, of_scroll_to et la recherche l'attendent ; lisez la table dans ue_loaded
markdownview : une colonne alignée par l'auteur (:--, --:) dans une application de droite à gauchechangeait de côtégarde son côté ; seul l'alignement par défaut suit le sens
markdownview : ue_load_failed pour un texte posé par is_markdownjamais levélevé (REASON_FAILED, as_source vide) pour un texte que le composant ne sait pas lire ; le document précédent reste affiché
menubar : un raccourci d'entrée (is_shortcut)agissait sur l'état laissé par la dernière ouverture du menulève d'abord ue_menu_opening de son menu, comme Windows : une entrée que cet événement grise ne répond pas, et ue_menu_closed le dit
menubar : une ouverture abandonnée avant de s'afficher (glissement rapide, Échap ou Alt pendant ue_menu_opening, perte du focus)ue_menu_opening sans ue_menu_closed ; après Échap, le déroulant s'ouvrait quand mêmerien ne s'ouvre, et ue_menu_closed suit : chaque ue_menu_opening reçoit exactement un ue_item_selected ou un ue_menu_closed
menubar : Alt puis Échap, F10 puis ÉchapÉchap partait aussi à la fenêtre : son bouton AnnulerÉchap quitte le mode menu et reste à la barre
menubar : un menu ouvert au clavier (Alt+lettre, F10 puis Entrée)aucune entrée en surbrillance : Entrée ne choisissait rienla première entrée est en surbrillance, Entrée la choisit
menubar : Alt quand la barre a déjà le focusle mode menu basculait à l'appui : Alt+Maj (disposition du clavier) l'allumaitau relâchement d'un Alt seul, comme Windows
menubar : un clic sur un titre grisé ou sur le vide de la barrela barre gardait le clavier, le champ en saisie le perdaitle clavier reste au contrôle où l'on tapait
menubar : is_shortcut posé sur une adresse qui ne nomme aucune entréela touche était prise dans toute la fenêtre, même après of_clearrien n'est armé : posez-le après of_add_item
pdfviewer : ib_allow_save / ib_allow_print d'une visionneusevalaient pour toutes les visionneuses de l'application ; un of_reset ailleurs rendait Enregistrer à un document confidentielchaque visionneuse garde son réglage
pdfviewer : ib_allow_save / ib_allow_print posés avant is_sourcetrois chargements, trois ue_load_completed ; un document en échec était retenté à chaque changementun seul chargement ; un document en échec n'est pas retenté
pdfviewer : ii_page posé pendant qu'un document est affiché, puis un autre is_sourcele document suivant s'ouvrait à cette pagela page était celle du document affiché : le suivant s'ouvre à sa première page ; pour ouvrir un document sur une page, posez is_source puis ii_page
pdfviewer : la même valeur reposée (ii_page, ii_zoom, is_fit, ib_viewer_toolbar)rechargeait le document et relevait ue_load_completedne fait rien
pdfviewer : ii_zoom hors de 25 à 500transmis tel quel au lecteurramené dans 25 à 500, relu tel qu'appliqué
pdfviewer : une adresse https://nom:secret@… ; une source faite d'espacesposée dans le lecteur, qui la refusait sous une raison approximative, le secret repartant dans les événements ; relue telle quelle, of_refresh rendait 0refusée tout de suite par ue_load_failed (REASON_UNSUPPORTED) : téléchargez le document par le restclient ; relue "", of_refresh rend -4
picture : id_max_zoom sur une image plus grande que son cadrela molette, + et id_zoom montaient jusqu'à la taille réelleils s'arrêtent au plafond ; seule la touche 1 va au-delà
picture : une nouvelle is_source, ou ib_zoomable = false, sur une image zooméele zoom revenait à 1.0 sans rien direue_zoom_changed(1.0) est levé (of_reset reste muet) ; posez id_zoom après is_source
picture : un chemin entouré de blancs (colonne CHAR)refusé, REASON_UNSUPPORTEDaffiché ; is_source se relit tel qu'écrit
picture : touches du zoom avec Ctrl, Alt ou Windows enfoncéCtrl++ zoomait, Alt+1 montrait la taille réellelaissées à votre application (raccourcis, mnémoniques)
picture : une image recolorée (mono:, tint:) d'un autre site, dont le serveur refuse les requêtes d'une autre origineue_loaded et un cadre videue_error avec REASON_FAILED, le message dit pourquoi
radialmenu : is_tooltip, is_super_tooltip_title, is_super_tooltip_text, is_super_tooltip_imageexistaient, ne montraient jamais rien : le lanceur n'a pas de surfaceretirées : le compilateur montre la ligne, supprimez-la
radialmenu : of_close, un second of_show, of_clear ou of_reset pendant qu'une roue est ouverteue_dismissed venait quand la roue quittait l'écran ; of_is_open restait vrai jusque-làue_dismissed aussitôt, une fois par ouverture ; of_is_open faux dès le retour de l'appel
radialmenu : of_remove_item d'une branche que la roue ouverte ne montre pas (masquée)la roue se fermait (ue_dismissed)la roue reste ouverte ; elle ne se ferme que si elle montrait la branche
radialmenu : of_remove_item avec une clé nue ("csv")-5résolue comme par of_item (la seule branche qui la porte) ; -5 si deux branches la partagent
radialmenu : of_show d'une roue sans rien à montrer pendant qu'une autre est ouverteue_dismissed, et l'ancienne roue restait à l'écranl'ancienne roue se ferme aussi : un ue_dismissed pour chaque ouverture
radialmenu : il_back_color_hover d'une branche sans il_text_color_hoverle libellé pointé gardait le texte du thème (blanc sur rose pâle en thème sombre)un texte lisible sur cette teinte est choisi ; une couleur que vous posez n'est jamais changée
restclient : ib_windows_auth ou is_client_certificate, et une redirection vers un autre hôteles identifiants Windows et le certificat suivaient la redirectionseuls l'hôte et le port de la requête les reçoivent : l'autre hôte reçoit la requête sans eux
restclient : une valeur d'en-tête au-delà du Latin-1 (grec, japonais…)acceptée par of_set_header (0), puis chaque requête de l'objet rendait -5refusée dès of_set_header (-5, of_get_last_error() dit pourquoi) ; of_set_basic les accepte : sa paire part en base64 de son UTF-8
restclient : une méthode mal formée ("GE T"), des identifiants dans l'URL (https://user:mdp@…), un nom de champ d'of_upload qui contient un guillemet-4 « request failed: 0 » ; les identifiants disparaissaient sans un mot ; le corps multipart était cassé-5, et la raison dans of_get_last_error() (pour des identifiants : prenez of_set_basic)
restclient : une 303, ou une 301 ou 302 après un POST, qui repart en GETgardait le Content-Type du corps de départpart sans Content-Type
restclient : ue_progresslevé pour tout corps asynchrone, sans jamais atteindre le total : une barre restait à 39 %levé pour tout corps asynchrone (la doc le dit), et le dernier, juste avant ue_response, vaut le total
restclient : of_response_header d'un en-tête envoyé plusieurs fois (Link, Set-Cookie)la première valeur seulementtoutes, jointes par , — Set-Cookie par un saut de ligne
restclient : le User-Agent envoyéPBToolboxAI/4.0, écrit en durla version de la bibliothèque ; of_set_header("User-Agent", …) le remplace toujours
restclient : une requête quand le client HTTP n'a pas pu être créépartait sur une session jetable, sans authentification Windows, certificat client ni cookies-2, et il_status le dit
restclient : of_set_header("Authorization", …) après of_set_basicles deux authentifications partaientune seule authentification : l'Authorization posée remplace le Basic
ribbon : une valeur écrite par le code (is_text, id_value) pendant que le champ d'un combo ou d'un compteur a le focusle champ gardait l'ancien texte ; en le quittant, ue_combo_changed / ue_value_changed partait avec l'ancienne valeur, qui remplaçait la vôtrele champ l'affiche aussitôt, sauf si l'utilisateur est en train de taper (sa saisie gagne) ; quitter le champ sans avoir tapé ne lève rien
ribbon : un libellé à balises (is_label, titre d'onglet, de groupe, de bandeau, bouton applicatif)affiché tel quel, balises comprises (le panneau d'un groupe replié, lui, les interprétait)le balisage riche est interprété partout ; un texte de l'utilisateur passe par of_escape_markup
ribbon : la molette au-dessus du rubanchaque petit mouvement d'un pavé tactile changeait d'onglet ; un ruban replié changeait aussi d'onglet sans rien montrerun onglet par cran de molette (les petits mouvements se cumulent) ; rien sur un ruban replié
ribbon : of_add_spinner avec un pas de 0 ou moins, ou un minimum au-dessus du maximum ; id_min / id_max / id_step incohérentsacceptés : flèches mortes ou inversées, une valeur hors de la plage affichéeof_add_spinner rend -5 et borne la valeur à la plage ; un pas de 0 ou moins est refusé (of_get_last_error dit pourquoi) ; une borne posée au-delà de l'autre l'emmène avec elle, comme dans un NumericUpDown — l'ordre des deux écritures ne compte plus
ribbon : un is_keytip qui n'est pas fait de lettres A-Z et de chiffres ("É", "-")gardé et relu, jamais atteignable au clavierrefusé : rien ne change, of_get_last_error dit pourquoi
ribbon : Échap au second niveau des touches d'accès (les commandes d'un onglet)fermait toutes les touchesremonte aux lettres des onglets, comme dans Office ; un second Échap ferme
speechout : of_speak_from(0) ou un nombre négatiflisait depuis la première phrase-5, rien n'est lu (les positions comptent à partir de 1)
speechout : ii_rate, ii_pitch, ii_volume posés hors de leur intervalle (ii_rate = 1000)se relisaient tels que posés (1000) alors que la voix appliquait la bornese relisent tels qu'appliqués (400)
speechout : un morceau [rate]…[/rate] dans une phraseune phrase à lui : son ue_sentence, son numéro, et un point après [/rate] devenait une « phrase »reste dans sa phrase : un seul ue_sentence au texte entier, un seul numéro, ue_word compte dans ce texte, of_spoken_text une ligne par phrase ; la ponctuation part avec le morceau
speechout : [rate=0]lu à 100 %le débit le plus lent, 10 %
speechout : une règle de of_add_replacement sur un mot qui est aussi le nom ou la valeur d'une balise (total avec [mark=total], rate, un mot dans [spell])réécrivait la balise : la marque changeait de nom, la balise était lue à voix haute, le texte épelé changeaitla règle ne réécrit que le texte entre les balises
speechout : un poste sans aucune voixue_error, puis une lecture « en cours » : ue_started, chaque ue_sentence, ue_stopped ; of_speak_sync rendait 0ue_error et rien d'autre : aucune lecture, pas de ue_started ; of_speak_sync rend -4
speechout : is_lang sans région ("fr", "en")ue_voice_fallback à chaque lectureaucun repli pour une voix de cette langue, quelle que soit sa région
speechout : of_clear_queue derrière un of_speak (la lecture en cours n'est pas un texte de la file)ue_queue_done à la fin de la lecturepas de ue_queue_done : aucun texte de la file n'a été lu
speechout : une initiale (John F. Kennedy), un mois abrégé (Oct. 10), un sigle à points (U.S.)terminait la phrasereste dans la phrase (un mois ou un sigle la termine devant une majuscule, comme etc.) : les numéros de phrase peuvent changer
statusbar : un panneau cliquable grisé qui porte une infobullel'infobulle ne s'affichait jamaiselle s'affiche, pour dire pourquoi le panneau est grisé
statusbar : of_count, of_keys_at, of_has sur l'adresse d'un panneau ("enc")0, "", false : les entrées de sa liste n'étaient pas vuesles entrées de sa liste, séparateurs exclus
statusbar : une position dans une liste déroulante (of_insert_menu_item, of_move_menu_item)comptait les séparateurscompte les entrées seulement, comme les positions des panneaux
statusbar : une clé de panneau ou d'entrée qui commence par __acceptéerefusée, -5 : elle est réservée au composant
statusbar : is_tooltip et les cinq couleurs sur une entrée de liste (of_menu_item)gardés et relus, sans effetignorés, relus vides (-1 pour une couleur) : le menu natif ne les montre pas
statusbar : la poignée (ib_show_resize_grip) dans une feuille MDI, ou une barre qui n'est pas au bas de sa fenêtreelle redimensionnait le cadre, par son coinelle redimensionne la feuille ; pas de poignée quand la barre n'occupe pas le coin bas
statusbar : la touche Menu ou Maj+F10 sur un panneau qui a le focusrienue_panel_rclicked, au coin bas-gauche du panneau
stepbar : Entrée ou Espace sur une étape, dans une fenêtre qui a un bouton par défautue_step_clicked et le bouton par défaut (« Suivant ») se déclenchaitue_step_clicked seulement : la touche reste à la barre
stepbar : of_clear_steps quand la barre se tient sur une étapene levait rienue_step_changed(rang quitté, clé quittée, 1, ""), comme le retrait de l'étape en cours ; of_reset, lui, ne lève rien
stepbar : ii_current au-delà de « tout terminé » (plus loin que le nombre d'étapes + 1)ue_step_changed annonçait tout de suite un rang qui n'existait pas ; l'arrivée de l'étape était muetterien n'est levé tant que la barre attend ; ue_step_changed est levé quand l'étape arrive
stepbar : of_move_step sur une barre « tout terminé »pouvait rouvrir la barre : une étape repassait en cours, avec ue_step_changedla barre reste « tout terminé », rien n'est levé
stepbar : NAV_VISITED, une étape insérée ou déplacée devant l'étape en courscliquableaffichée terminée, mais pas cliquable : elle n'a jamais été atteinte
stepbar : une étape en avertissement (STATE_WARNING)une pastille ambreune pastille ambre et un second anneau ambre : elle ne ressemble plus à une étape faite là où l'accent est ambre
statictext : ue_hyperlink(string as_url)(string as_url, boolean ab_opened) : un script déjà écrit pour l'événement reste valable ; ab_opened vaut FALSE quand le lien ne s'est pas ouvert (schéma autre que http, https, mailto — of_get_last_error() dit pourquoi —, ou gardé fermé par ue_hyperlink_opening)
statictext désactivé sur un fond à lui (il_back_color, une portion [bk])le texte prenait le gris du thème, illisible sur un fond foncé ou coloréses couleurs sont gardées et atténuées ; sur la surface du thème, le gris du thème, comme avant
statictext : PBT_SetDefaultFont avec une taillela taille restait à 11 ptla taille donnée s'applique (11 pt sans elle, inchangé)
statictext : ii_font_size hors de 6 à 200appliquée telle quelleramenée à la borne la plus proche, comme la balise [size], et relue telle qu'appliquée
statictext : double-clic sur un mot avec ib_selectableun seul ue_clicked avant ue_double_clickeddeux ue_clicked puis ue_double_clicked, comme le StaticText de PowerBuilder ; relâcher après un glisser qui sélectionne reste sans clic
statictext : of_reset d'un texte annoncé coupérienue_text_overflow(false)
statictext : is_text relu après of_append_text, quand une ligne laissait une balise ouverte[b]Start[br]two : reposé, le gras courait sur la ligne suivante[b]Start[/b][br]two, ce que l'écran montre ; une ligne vide garde sa hauteur ; sous ib_marquee, les lignes défilent sur une seule ligne
statictext : ib_auto_width et un texte vidégardait la largeur du texte précédentse resserre à sa marge ; un changement de thème remesure aussi la largeur
xml : of_count, of_get_values, of_get_attrs, of_get_attr_names quand rien n'est chargé, qu'un élément bâti est encore ouvert ou que le moteur refuse l'XPathrendaient 0, comme une recherche sans résultatrendent -4 (-2 si la page ne répond pas), of_get_last_error() dit pourquoi ; 0 est toujours un vrai zéro. Un test > 0 ne change pas ; un test = 0 qui voulait dire « rien trouvé » voit désormais le refus à part
xml : of_get_attr et of_remove_attr d'un attribut absent, of_get_attrs avec un nom videvide sans raison, 0 (« fait »), 0vide et « no such attribute » dans of_get_last_error() (un attribut écrit vide reste sans raison), -4, -5
xml : of_set_value, of_set_attr, of_add_child d'un texte qui porte un caractère de contrôle (Char(1)) ou un CRécrit tel quel : le document ne se rechargeait plus, le CR revenait en LFle caractère interdit est retiré, comme par le builder ; le CR s'écrit &#13; et se relit
xml : builder — un second élément au sommet, un texte sans élément ouvert, un attribut après un enfantécrit (deux racines) ou ignoré sans un motlaissé de côté, et of_get_last_error() dit pourquoi
xml : of_get_value("sum(//qty)") sur un texte non numérique ; of_get_value("/")le texte NaN ; videvide et « the expression is not a number » ; le texte du document

La recette : rien à changer.

12.6 Ce qui a été ajouté #

Rien de ce qui suit ne demande de modifier votre code. Les huit nouveaux composants de la 5.0 sont présentés dans les notes de version.

ObjetAjouté
progressbaris_unit : un texte écrit après la lecture ("of 500 rows", "MB")
datagridis_mask d'une colonne (n_pbt_datagrid_column) : le masque de saisie d'une colonne numérique ; une colonne sans format d'affichage montre son is_mask
datagridle clavier des en-têtes (Flèche haut depuis la première ligne ; Entrée trie, Maj+Entrée ajoute au tri ; Alt+Bas ou la touche Menu ouvre le menu de la colonne ; Ctrl+Maj+flèches la déplacent, Alt+flèches changent sa largeur) ; TYPE_TIME ; of_get_last_error dit pourquoi un appel a rendu -5
ribbonis_mask et is_format d'un compteur (n_pbt_ribbon_item) ; is_group : bascules exclusives d'un groupe (n_pbt_ribbon_item) et entrées radio d'un menu (n_pbt_ribbon_menu_item) ; ue_item_rclicked (clic droit sur un contrôle, un groupe, un onglet ou un bouton de la barre d'accès rapide, avec le point d'écran al_x, al_y ; touche Menu et Maj+F10 aussi) et ue_rclicked (hors item) ; is_title d'un groupe contextuel (n_pbt_ribbon_ctx_group), dont l'info-bulle s'affiche sur le bandeau ; touches d'accès des boutons de la barre d'accès rapide ; couleurs d'item des entrées de menu et des boutons de la barre d'accès rapide ; noms accessibles de tous les contrôles
breadcrumbla saisie du chemin devient une barre d'adresse : ib_auto_complete, ue_path_typing et of_add_suggestion (complétion pendant la frappe), ib_veto_path, ue_path_entering et is_path_error (un chemin refusé garde la saisie)
chartcartesianof_from_datastore (DataStore, DataWindow, DataWindowChild), of_map et les constantes ROLE_*, of_reload : le graphique d'un DataWindow (lignes sommées par catégorie et série, relu en place) ; of_set_point_color / of_get_point_color ; ue_point_rclicked, ue_rclicked ; of_get_categories ; of_remove_axis_section
codeeditorof_undo, of_redo, ib_can_undo, ib_can_redo et ue_undo_state_changed (l'historique d'annulation pilotable) ; ue_modified_changed ; of_toggle_comment (Ctrl+/) ; of_next_marker (F8) ; ib_match_brackets ; ib_tab_moves_focus (Ctrl+M)
cryptoles blobs (of_base64_encode_blob, of_base64_decode_blob, of_hash_blob, of_hmac_blob, of_crc32_blob, of_encrypt_blob, of_decrypt_blob) ; of_base64_encode_file_to_file ; of_jwt_verify_jwks, of_jwk_to_pem, of_pem_to_jwk ; les claims attendues de of_jwt_verify et il_jwt_leeway_seconds ; JWT_HS384/HS512, JWT_RS384/RS512, JWT_PS256/PS384/PS512, JWT_ES384 et KEY_EC_P384 ; le schéma et le hachage de of_sign / of_verify (SIGN_PKCS1, SIGN_PSS) ; les données associées de of_encrypt_with_key / of_decrypt_with_key ; le hachage de of_rsa_encrypt / of_rsa_decrypt ; les réglages de of_totp_code, of_totp_verify, of_totp_uri et of_hotp_code ; of_password_needs_rehash
buttonbaris_style d'un bouton (STYLE_PRIMARY, STYLE_FLAT, STYLE_DANGER), is_badge (une pastille de texte), il_badge_color, is_mnemonic, ii_image_size et ii_badge_size de la barre, ib_enabled de la barre entière, ue_button_rclicked et ue_rclicked, of_clear_shortcuts
commandpaletteof_load_menu(menu) : la palette remplie depuis un menu PowerBuilder, relu à chaque ouverture ; of_loaded_item(as_key) rend l'item d'une commande ; of_get_last_error()
dockcontainerib_front d'un panneau (n_pbt_dock_panel, lecture seule) : le panneau que sa pile montre ; l'entrée Masquage automatique du menu de panneau, aussi sur la languette du rail ; Maj+F10 et la touche Menu ouvrent ce menu sous l'onglet ; le panneau actif, celui qui a le clavier : of_active_panel() et ue_active_panel_changed(as_key)
crosstabof_value(position) et sa poignée n_pbt_crosstab_value (une valeur de la zone Valeurs : is_agg, is_show, is_conditional_formatting, is_format, ib_negative_red, is_label, of_field()) ; of_value_count, of_remove_value, of_move_value ; of_get_cell_rows (les lignes du DataStore derrière une cellule) ; is_format d'un champ ; AGG_COUNT_ROWS, LABEL_BEFORE, LABEL_AFTER
messageboxof_messagebox (les arguments de MessageBox(), Question!, YesNo! compris) et les constantes BUTTONS_* ; of_retry_cancel ; le bouton par défaut de of_confirm, of_yes_no, of_yes_no_cancel (al_default) ; Réessayer, Abandonner, Ignorer, Fermer traduits ; ib_closable, ib_sound ; is_details, is_details_label ; is_footer, is_footer_icon ; ib_input_multiline, il_input_max_length, is_input_pattern, is_input_error ; of_prompt qui masque et exige ; un choix désactivé (of_add_choice, ab_enabled)
jsontreeof_get_layout, of_set_layout et ue_layout_changed (les plis, la sélection, la ligne du haut) ; of_selected_addressable, of_selected_type, of_selected_count, of_copy_path ; ue_node_rclicked (clic droit, touche Menu) ; ib_find_decoded (la recherche dans les valeurs décodées, bascule &)
xmltreeof_find_xpath (chaque nœud d'un XPath, parcouru par of_search_next) ; of_get_layout, of_set_layout et ue_layout_changed (les plis, la sélection, la ligne du haut) ; of_selected_kind (constantes KIND_*), of_selected_name, of_selected_namespace, of_copy_path ; ue_node_rclicked (clic droit, touche Menu) ; ib_find_decoded (la recherche dans les valeurs décodées, bascule &)
jsonof_from_datastore et of_to_datastore (DataStore, DataWindow, DataWindowChild) : un DataStore en tableau d'objets typés, et retour ; dates ISO 8601 (of_set_date, of_set_datetime, of_set_time, of_add_date, of_add_datetime, of_add_time, of_get_date, of_get_datetime, of_get_time) ; of_get_last_error et of_error_position (où un texte n'est pas du JSON) ; of_escape_key
listbarue_item_invoked (un clic sur l'entrée, déjà sélectionnée comprise) ; ib_search, is_filter, ue_filter_changed (une recherche) ; of_from_datastore (DataStore, DataWindow, DataWindowChild), of_map et les constantes ROLE_* (une ligne = une entrée)
markdownviewis_base_path, ib_allow_html (une courte liste de balises HTML inertes), ib_network_pictures, ib_remote_pictures, ib_tasks_editable et ue_task_toggled, ib_track_heading et ue_heading_visible, is_position, ii_zoom, of_selected_text, of_copy et Ctrl+Inser, les constantes LINK_* ; les alertes GitHub, les adresses e-mail nues et les émojis
menubarof_load_menu(menu) : toute la barre depuis le menu PowerBuilder d'une fenêtre, relu à chaque ouverture, ses Clicked exécutés ; of_loaded_item ; of_insert_item (une entrée à un rang) et of_clear_items (vider une cascade en gardant l'entrée) ; of_open, of_close, of_is_open
pdfviewerof_load_blob(blob) et of_load_blob(blob, string) : un PDF tenu dans un blob (lu par SELECTBLOB), affiché sans fichier, quelle que soit sa taille ; is_find (un texte surligné à l'ouverture) ; ib_navigation_pane (le panneau latéral du lecteur) ; is_destination (ouvrir sur une destination nommée du PDF) ; ib_allow_search, ib_allow_rotate et ib_allow_fullscreen (les commandes Rechercher, Faire pivoter et Plein écran de la barre du lecteur)
pictureof_set_picture(blob) : une image tenue en mémoire (SelectBlob), comme SetPicture du Picture natif ; ib_clickable : l'image devient un bouton au clavier (Tab, Entrée, Espace) ; les formats TIFF, WMF, EMF et RLE, convertis à la volée ; un nom pour les lecteurs d'écran qui dit la pastille et l'échec
radialmenuof_show_over(dragobject ado_control {, boolean ab_keyboard}) : la roue centrée sur un contrôle, sa première branche allumée quand elle vient du clavier ; sur la poignée de branche, is_image (icône changée en place), is_tone (constantes TONE_* de u_pbt_radialmenu) et is_group (groupe radio)
restclientof_url et of_url_encode (une requête d'URL encodée) ; of_post_form et of_post_form_async (un formulaire HTML) ; of_oauth_client_credentials (un jeton OAuth2 renouvelé de lui-même) ; of_retrieve (DataStore, DataWindow, DataWindowChild : un tableau JSON en lignes) ; les en-têtes d'une seule requête (of_request et of_request_async, quatrième argument as_headers) ; is_last_request ; ib_check_revocation
statusbarib_spring (et une largeur de -1 dans of_add_panel, of_insert_panel) : un panneau qui prend la place libre ; of_dock_bottom (la barre au bas de sa fenêtre) ; is_help et is_help_panel (la MicroHelp d'un cadre PowerBuilder) ; ib_announce (lecteurs d'écran) ; l'infobulle d'un texte élidé
tilesboxof_move_tile(as_keys, as_to_key, al_position) : une tuile envoyée par le code dans un autre groupe, avec ses couleurs, sa pastille et ses faces ; Échap annule un glisser, le panneau défile quand le pointeur approche de son bord ; un lecteur d'écran entend la pastille et le bandeau d'une tuile ; une icône SVG reste nette sur une grande tuile ; l'entête d'un groupe s'éclaire au survol ; « moins d'animations » de Windows respecté
statictextib_mnemonic (le & d'un libellé PowerBuilder), ii_max_lines (au plus N lignes, « … »), il_max_log_lines et of_clear (un journal borné, vidé), ii_max_width (plafond de ib_auto_width), ib_veto_links et ue_hyperlink_opening (décider si un lien s'ouvre) ; un journal est annoncé ligne à ligne aux lecteurs d'écran ; désactivé, les zones du balisage sortent de l'ordre de Tab
xmlof_get_number, of_get_decimal, of_get_longlong, of_get_boolean, of_get_date, of_get_datetime : la valeur à l'XPath vérifiée contre son type XML Schema et lue pareil sur tout poste (NULL et of_get_last_error() si elle n'est pas de ce type)
xmlsurcharges decimal, date, datetime, boolean de of_leaf, of_element_attr et of_set_value : écrites avec un point et en ISO 8601 quel que soit le poste

12.7 buttonbar : la clé, le libellé puis l'icône ; le « & » et l'accord #

La barre de boutons parlait autrement que le reste de la bibliothèque : l'icône avant le libellé, la position en deuxième argument, et un is_shortcut qui voulait dire « lettre Alt » là où il veut dire « accord » partout ailleurs — is_shortcut = "Ctrl+S" armait Alt+C. La 5.0 l'aligne sur button, la barre d'outils et le CommandButton de PowerBuilder.

Quoi4.05.0
Ajouter un boutonuo.of_add_button("save", "img\save.png", "Save")uo.of_add_button("save", "&Save", "img\save.png")
Un bouton texte seuluo.of_add_button("ok", "", "OK")uo.of_add_button("ok", "OK")
Insérer un boutonuo.of_insert_button("mid", 2, "", "Mid")uo.of_insert_button("mid", "Mid", "", 2)
La lettre Alt d'un boutonis_shortcut ← "S" (Alt+S)le libellé "&Save", ou uo.of_button("save").is_mnemonic = "S"
Un accord sur un boutonuo.of_register_shortcut("Ctrl+S", "save")le même, ou uo.of_button("save").is_shortcut = "Ctrl+S" — affiché dans l'info-bulle
Un « & » dans un libelléaffiché tel quelmarque la lettre Alt ; && pour un « & » écrit
La pastilleuo.of_button("inbox").il_badge = 3uo.of_button("inbox").is_badge = "3" (un texte : "New", "!") ; il_badge reste accepté
Le bouton focalisé, sans is_defaultpeint en accent pleinson anneau de focus seulement
// 4.0 : the icon before the label
uo_bar.of_add_button(/*key*/ "save", /*image_file*/ "img\save.png", /*text*/ "Save")

// The Alt letter went to is_shortcut (the letter S alone), the chord to of_register_shortcut
uo_bar.of_register_shortcut(/*chord*/ "Ctrl+S", /*key*/ "save")
// 5.0 : key, label, icon - the "&" of the label gives Alt+S
uo_bar.of_add_button(/*key*/ "save", /*text*/ "&Save", /*image*/ "img\save.png")

// The chord is a property of the button, shown in its tooltip
uo_bar.of_button(/*key*/ "save").is_shortcut = "Ctrl+S"

La recette : compilez ; un appel d'of_insert_button est signalé (la position passe en dernier). Un of_add_button à trois arguments compile toujours : échangez les deux derniers (le libellé, puis l'icône) — un bouton dont le libellé est un chemin de fichier vous montre ceux qui restent. Remplacez chaque is_shortcut d'une lettre par un « & » dans le libellé, et doublez tout « & » qui doit s'afficher (R&&D).

12.8 crosstab : le format des valeurs par is_format #

Le croisé écrivait les nombres d'une mesure par une fonction à quatre ou cinq arguments (décimales, séparateur de milliers, symbole, symbole devant), qui valait pour toutes les valeurs d'un champ : le même champ deux fois en Valeurs — le montant, et sa part du total — ne pouvait pas avoir deux formats. La 5.0 le range sous la langue des graphiques et des jauges : un format d'affichage PowerBuilder dans is_format, sur la poignée du champ (of_field) pour toutes ses valeurs, ou sur la poignée d'une valeur (of_value(position), nouvelle) pour elle seule. Vide, une valeur prend le Format de la colonne du DataWindow. Aucun ancien nom ne survit.

Quoi4.05.0
Le format de toutes les valeurs d'un champuo.of_set_value_format("amount", 2, "locale", "$", true)uo.of_field("amount").is_format = "$#,##0.00"
Un symbole après le nombreuo.of_set_value_format("amount", 0, "", " EUR")uo.of_field("amount").is_format = '#,##0" EUR"'
Le format d'une valeur (le même champ deux fois)—uo.of_value(2).is_format = "#,##0.00"
Les négatifs en rougele menu de la puce seulementuo.of_value(1).ib_negative_red = true
Revenir au format par défautuo.of_clear_value_format("amount")uo.of_field("amount").is_format = "" (le Format de la colonne du DataWindow)
// 4.0 : decimals, thousands, symbol and its side as arguments - for every value of the field
uo_cross.of_set_value_format(/*field*/ "amount", /*decimals*/ 2, /*thousands*/ "locale", /*suffix*/ "$", /*symbol_before*/ true)
// 5.0 : a display format, written as in a DataWindow - for the field, then for its second value alone
uo_cross.of_field(/*field*/ "amount").is_format = "$#,##0.00"
uo_cross.of_value(/*position*/ 2).is_format = "#,##0"

La recette : compilez ; chaque of_set_value_format et of_clear_value_format est signalé. Écrivez le format comme dans une DataWindow : ai_decimals donne le nombre de 0 après le point, un séparateur de milliers donne le , du groupement ("none" : aucun), le symbole s'écrit devant ou derrière (entre guillemets s'il contient des chiffres ou des espaces). Le format d'une seule valeur va dans of_value(<position>).is_format.

12.9 listbar : le clic droit porte son point, une disposition s'annonce #

La barre latérale rejoint la bibliothèque sur trois points : le clic droit d'une entrée donne son point d'écran comme celui des arbres, des grilles et du kanban ; un ordre du code qui change la disposition l'annonce comme un geste ; une entrée grisée ne devient plus la sélection. Elle gagne aussi un événement pour le clic sur l'entrée déjà sélectionnée, une recherche et la construction depuis un DataStore (12.6).

Quoi4.05.0
ue_item_rclicked(string as_keys)(string as_keys, long al_x, long al_y) : le point en pixels d'écran ; la touche Menu et Maj+F10 le lèvent aussi
of_set_layout qui change la dispositionaucun événementun ue_layout_changed (jamais ue_section_toggled)
of_move_item / of_move_section vers le rang déjà tenuue_layout_changedrien : rien n'a bougé
of_select_item d'une entrée grisée0, elle devenait la sélection-5, sans poser ue_selection_changing ; griser l'entrée déjà sélectionnée la garde
ib_auto_width relu pendant que la barre est en railtruece que l'application a posé
of_item d'une adresse à un seul niveau ("nav")atteignait la sectionune poignée qui ne nomme rien ; une section s'atteint par of_section
La même lettre tapée deux foisun préfixe dd, souvent sans correspondancela ligne suivante qui commence par elle ; un Espace au milieu d'un préfixe lui appartient
Une entrée grisée sous le pointeursans info-bulleson info-bulle s'affiche ; le clic ne fait toujours rien
// 4.0 : PointerX() of the userobject - the menu opened too high under a ribbon
m_entry.PopMenu(PointerX(), PointerY())
// 5.0 : the pointer of the WINDOW for a PowerBuilder menu (al_x, al_y serve a menu of the library)
m_entry.PopMenu(parent.PointerX(), parent.PointerY())

La recette : rien ne refuse de compiler — un script de ue_item_rclicked garde as_keys. Ouvrez votre menu au pointeur de la fenêtre (parent.PointerX()), ou passez al_x, al_y à of_show d'un contextmenu. Posez la sélection initiale avant d'armer ib_veto_selection, et vérifiez que votre ue_layout_changed accepte l'appel que lève désormais of_set_layout.

12.10 scheduler : la nature d'un changement et les valeurs d'avant #

Le calendrier rejoint le diagramme de Gantt : la question posée avant un geste dit s'il s'agit d'un déplacement ou d'un redimensionnement, et les événements qui suivent donnent les valeurs d'avant — un journal, une annulation ou une confirmation n'ont plus à garder leur copie de chaque rendez-vous. Une sélection que votre code retire est annoncée, et quatre appels refusent désormais ce qu'ils acceptaient en silence.

Quoi4.05.0
ue_appointment_changing(string as_key, string as_start, string as_end, string as_resource)(string as_key, string as_kind, string as_start, string as_end, string as_resource) : as_kind vaut CHANGE_MOVE ou CHANGE_RESIZE
ue_appointment_moved(string as_key, string as_start, string as_end, string as_resource)(string as_key, string as_start, string as_end, string as_resource, string as_old_start, string as_old_end, string as_old_resource)
ue_appointment_resized(string as_key, string as_start, string as_end)(string as_key, string as_start, string as_end, string as_old_start, string as_old_end)
Votre code retire, vide ou recharge le rendez-vous sélectionnéaucun événementue_selection_changed("") ; of_reset reste muet
of_add_appointment dont la fin précède le début0, la fin devenait début + 30 min-5, of_get_last_error dit pourquoi
of_scroll_to_time("abc")0, rien ne défilait-5
of_set_field sur la colonne qui joue ROLE_KEY0, deux rendez-vous d'une même clé-5 : une clé change en rechargeant
of_show_appointment d'un rendez-vous masqué, filtré ou sur une ressource masquée0, la vue partait vers un jour où rien ne se voyait-5, rien ne bouge
is_now posé après une navigation de l'utilisateurramenait la vue à son jourla vue reste où l'utilisateur est allé
of_clear_appointmentsgardait les colonnes du DataStore pour of_mapoublie le DataStore : of_map accepte les colonnes du suivant
// 5.0 : ue_appointment_changing event of uo_sched : (string as_key, string as_kind, string as_start, string as_end, string as_resource) returns boolean
// A resize keeps the day : only a move is checked
if as_kind = u_pbt_scheduler.CHANGE_RESIZE then return true

// Nothing on a Saturday or a Sunday : returning false puts the appointment back
if DayNumber(Date(Left(as_start, 10))) = 1 or DayNumber(Date(Left(as_start, 10))) = 7 then return false
return true

La recette : rien ne refuse de compiler — un script de ue_appointment_changing, ue_appointment_moved ou ue_appointment_resized garde ses arguments, les nouveaux s'y ajoutent. Si votre ue_selection_changed active des boutons, il reçoit maintenant "" quand le rendez-vous sélectionné part ; relisez les codes retour d'of_add_appointment, of_scroll_to_time, of_set_field et of_show_appointment, qui peuvent désormais rendre -5. Pour enregistrer les gestes sans code, voyez ib_write_back.

12.11 shellexplorer : l'erreur dit sa raison #

L'explorateur du shell donne désormais, dans ue_error comme dans ue_path_not_found, une raison que votre code peut tester — une constante REASON_* de u_pbt_shellexplorer, la même dans toutes les langues de Windows. Il ne lève plus ue_selected pour le dossier déjà sélectionné, et annonce par ue_collapsed une branche qu'il referme de lui-même. Il gagne aussi le clic droit sur un dossier (ue_node_rclicked) et l'adresse de la racine.

Quoi4.05.0
ue_error(string as_message)(string as_path, string as_reason, string as_message) : le chemin ("" pour le Bureau), une constante REASON_*, le texte du shell
as_reason de ue_path_not_foundune phrase anglaise (not found, outside the root, not a branch…)une constante REASON_* (not_found, outside_root, not_a_branch…) ; not_shown pour un chemin qui existe mais que l'arbre ne montre pas
Re-sélectionner le dossier déjà sélectionné (clic, Début sur la première ligne)ue_selectedrien
Une branche que l'arbre referme de lui-même (revenue vide, refusée par le shell)aucun événementue_collapsed
ib_show_files, ib_show_hidden, is_file_filter, is_root écrits avec leur valeurl'arbre est relurien n'est relu ; is_file_filter posé sans les fichiers attend qu'ils soient montrés
of_collapse d'un chemin dessiné deux foischaque ligne, un ue_collapsed chacunela ligne qu'atteint of_select, un ue_collapsed
of_count(""), of_keys_at("", i)les lignes affichées, comme of_count()le premier niveau (la racine), comme of_count(is_root)
// 5.0 : ue_error event of uo_tree : (string as_path, string as_reason, string as_message)
// Test the reason, never the text of the shell
if as_reason = u_pbt_shellexplorer.REASON_TIMEOUT then
    st_status.text = "The network folder " + as_path + " does not answer"
else
    st_status.text = as_message
end if

La recette : rien ne refuse de compiler — un script de ue_error garde as_message, les nouveaux arguments s'y ajoutent. Un test sur le TEXTE de as_reason dans ue_path_not_found ("not found", "outside the root") se réécrit avec une constante REASON_* ; une application qui rechargeait un volet à chaque ue_selected le fait désormais une fois par changement.

12.12 tilesbox : le clic droit porte son point, un ordre du code s'annonce, la disposition laisse les droits à l'application #

Le panneau de tuiles rejoint la bibliothèque : son clic droit donne le point d'écran comme celui des arbres, des grilles et du kanban ; un ordre du code qui déplace une tuile, replie un groupe ou change une taille lève les mêmes événements qu'un geste ; la disposition ne porte plus la visibilité, qui reste l'affaire de l'application. Il gagne aussi le déplacement d'une tuile vers un autre groupe par le code (12.6).

Quoi4.05.0
ue_tile_context(string as_keys)ue_tile_rclicked (string as_keys, long al_x, long al_y) : le point en pixels d'écran ; la touche Menu et Maj+F10 le lèvent aussi, au coin bas-gauche de la tuile
of_move_tile, of_insert_tileinteger ai_indexlong al_position ; une surcharge of_move_tile(as_keys, as_to_key, al_position) envoie la tuile dans un autre groupe
of_move_tile vers une autre placerienue_tile_moved, ue_layout_changed
ib_collapsed d'un groupe posé par le codeue_group_toggledue_group_toggled, ue_layout_changed
is_size posé par le coderienue_layout_changed (jamais ue_tile_resized, qui dit que l'utilisateur l'a choisie)
is_size d'une taille inconnue ("huge")la tuile passait en mediumrefusé : rien n'est écrit, of_get_last_error dit pourquoi ; of_add_tile / of_insert_tile rendent -5
La disposition (of_get_layout, ue_layout_changed)portait la visibilité des groupes et des tuilesne la porte plus : of_set_layout ne ré-affiche jamais ce que votre code a masqué ; une disposition 4.0 se relit sans elle
of_set_layout qui change la dispositionaucun événementun ue_layout_changed ; -5 sur un JSON qui n'est pas une disposition ({})
of_tile / of_group d'une adresse qui ne nomme rienune poignée par appel, gardéela poignée inerte, la même pour toutes : elle n'écrit rien et se relit vide
// 4.0 : the right click of a tile
// ue_tile_context event of uo_tiles : (string as_keys)
// 5.0 : the same script, under the new name, with the screen point
// ue_tile_rclicked event of uo_tiles : (string as_keys, long al_x, long al_y)

La recette : compilez ; votre script de ue_tile_context reste sur un événement qui n'existe plus — déplacez-le dans ue_tile_rclicked, qui garde as_keys. Si votre ue_layout_changed enregistre la disposition, il voit désormais aussi ce que votre code change ; un ue_tile_moved qui ne doit réagir qu'à l'utilisateur ignore les déplacements que votre code vient de faire. Si vous rangiez la visibilité dans la disposition, posez-la par le code à l'ouverture (ib_visible), selon les droits.

12.13 tab : le clic droit porte son point, une disposition appliquée s'annonce #

L'onglet rejoint la bibliothèque : le clic droit d'un onglet, menu intégré coupé, donne son point d'écran comme celui des arbres, des grilles et du kanban, et of_set_layout qui change la disposition l'annonce comme un geste. Un glisser rendu à sa place n'annonce plus rien. Il gagne aussi des pages créées à la demande (ue_page_needed, of_supply_page), le double-clic (ue_tab_double_clicked), ib_cycle_keys, is_close_mode, ii_strip_width et, sur une page, ib_modified et is_badge — voir la page de l'onglet.

Quoi4.05.0
ue_tab_rclicked(string as_key)(string as_key, long al_x, long al_y) : le point en pixels d'écran ; la touche Menu et Maj+F10 le lèvent aussi, au coin bas-gauche de l'onglet
of_set_layout qui change la dispositionaucun événementue_layout_changed, une fois
un glisser rendu à sa place, of_move_page à sa propre placeue_tab_reordered et ue_layout_changedrien : l'ordre n'a pas changé
plusieurs déplacements sous of_set_redraw(false)un ue_layout_changed par déplacementun seul, à la reprise
Maj+F10 sur un onglet, menu intégréle menu s'ouvrait sous la sourissous l'onglet
bande verticale et titre longla bande prenait la largeur du titre40 % du composant au plus, points de suspension ; ii_strip_width la fixe
il_accent d'une pagel'anneau de focus seulementsouligne aussi l'onglet actif
is_shortcut sur la poignée d'une clé sans pageinscrit : la touche était prise pour rienrien n'est inscrit, of_get_last_error dit pourquoi
of_insert_page dont le déplacement échouecode négatif, la page restaitcode négatif, la page est retirée
// 4.0 : the right click of a tab, built-in menu off
// ue_tab_rclicked event of uo_tabs : (string as_key)
// 5.0 : the same script, with the screen point
// ue_tab_rclicked event of uo_tabs : (string as_key, long al_x, long al_y)

La recette : rien ne refuse de compiler — un script de ue_tab_rclicked garde as_key. Ouvrez votre menu au pointeur de la fenêtre (parent.PointerX()), ou passez al_x, al_y à of_show d'un contextmenu. Vérifiez que votre ue_layout_changed accepte l'appel que lève désormais of_set_layout.

12.14 soundplayer : le numéro d'un son, un refus rendu tout de suite #

Le lecteur de sons change trois choses que votre code peut voir. Ses événements portent le numéro du son : ue_started, ue_ended et ue_failed reçoivent un dernier argument, al_sound — le numéro que rendent désormais of_play_over et of_enqueue (ils rendaient 0), et que prend le nouveau of_stop_sound. Une source refusée d'emblée est un code : of_play, of_play_over, of_crossfade et of_preload rendent -5, la raison dans of_get_last_error(), pour une source vide, une adresse http://, une adresse file:// mal formée ou un format refusé par son nom — et ne lèvent plus ue_failed ; le son en cours continue. Dans la file (of_enqueue), le refus arrive toujours par ue_failed, à son tour. D'autres -5 : of_pause et of_resume sans rien à suspendre ou reprendre, of_beep et of_beep_sync à 0 Hz ou 0 ms, of_meter hors de 1 à 64 barres.

// Local variables
string ls_url
long ll_rc

// The address of the sound, typed by the user
ls_url = sle_url.text

// 4.0 : of_play returned 0, and an http:// address came back later through ue_failed
// 5.0 : the refusal is a code, at once ; of_get_last_error() gives the reason
ll_rc = inv_sound.of_play(/*source*/ ls_url)
if ll_rc = -5 then
	MessageBox("Sound", inv_sound.of_get_last_error())
end if

Ce qui change sans rien demander à votre code : of_stop s'éteint désormais sur il_fade_ms, comme la documentation le promettait (ue_stopped arrive toujours tout de suite) ; à l'échéance de il_timeout_ms, seul le son de l'appel synchrone est coupé — le fond, les superpositions et la file continuent ; of_crossfade vers une source refusée garde la piste en cours ; of_level vaut 0 et of_spectrum ne rend aucune barre, vumètre éteint ; of_equalizer(ab_on, ai_gains[]) remet à 0 une bande que le tableau n'atteint pas ; of_clear_queue oublie aussi les sons que la file a déjà joués ; les messages de ue_failed suivent la langue d'affichage (as_reason reste le mot à tester). Le lecteur gagne aussi la file navigable (of_next, of_previous, of_queue_index, ue_source_changed, ib_queue_repeat), la boucle sans blanc (ib_gapless_loop, REASON_TOO_LONG), le segment (of_play_range), le muet (ib_muted) et la mise en mémoire tampon (ue_buffering, of_is_buffering) — voir la page du lecteur de sons.

La recette : rien ne refuse de compiler — un script de ue_started, ue_ended ou ue_failed garde ses arguments, al_sound s'y ajoute. Relisez les tests de code retour d'of_play_over et d'of_enqueue (un = 0 devient > 0), et le code qui attendait ue_failed pour une adresse http:// ou une source vide : il teste maintenant le -5 de l'appel.

12.15 toaster : la raison d'une fermeture, un toast fermé par le code s'annonce toujours #

Le toaster dit pourquoi un toast s'est fermé : ue_toast_dismissed reçoit un dernier argument, as_reason — REASON_TIMEOUT, REASON_USER (sa croix), REASON_CODE (of_close, of_close_all) ou REASON_OWNER_CLOSED (sa fenêtre s'est fermée). Et tout toast fermé par le code l'annonce, même fermé juste après of_show, avant d'être dessiné, ou pendant qu'il attendait sa place : une application qui attendait ue_toast_dismissed pour libérer son état ne dépend plus d'une course.

Quoi4.05.0
ue_toast_dismissed(long al_id, string as_key)(long al_id, string as_key, string as_reason), constants REASON_*
of_close d'un toast pas encore dessiné, ou en attente de placerien n'était levéue_toast_dismissed, REASON_CODE
of_close d'un toast d'un autre toasterle fermait, l'annonce partait chez l'autre-5, rien n'est fermé, of_get_last_error dit pourquoi
la fenêtre d'ipo_owner se fermeses toasts disparaissaient sans rien direue_toast_dismissed, REASON_OWNER_CLOSED
un toaster détruit, toasts à l'écranils restaient, muetsles persistants et ceux à boutons se ferment avec lui ; les autres finissent seuls
of_show avant que le moteur d'affichage soit prêt-6 : « runtime absent »-4 : réessayer ; of_get_last_error dit pourquoi
coin d'un toast ancré à la fenêtrela fenêtre entière : le toast couvrait la barre de titre et ses boutonsla zone cliente (celle du cadre en MDI)
un titre très longpoussait la croix et les boutons hors de la fenêtreplafonné, il défile
// 4.0
// event ue_toast_dismissed de inv_toaster : (long al_id, string as_key)
// 5.0 : le meme script, avec la raison
// event ue_toast_dismissed de inv_toaster : (long al_id, string as_key, string as_reason)

La recette : rien ne refuse de compiler — un script de ue_toast_dismissed garde al_id et as_key, as_reason s'y ajoute. Relisez le code qui supposait qu'un toast fermé tout de suite par of_close ne dirait rien : il l'annonce maintenant. Les toasts restent accrochés au toaster qui les a montrés : un of_close sur l'identifiant d'un autre toaster rend -5. Le toaster gagne aussi of_close_all (fermer tous ses toasts) et of_get_last_error — voir la page du toaster.

12.16 video : un refus rendu tout de suite, un film et ses sous-titres d'un seul appel, le même film repris #

Le lecteur vidéo change cinq choses que votre code peut voir. Un refus est rendu tout de suite, comme au lecteur de sons (12.14) : of_play(), of_play(source) et of_play_range rendent -5, la raison dans of_get_last_error(), pour une source vide, une adresse http:// ou un format refusé par son nom (avi, wmv, flv) — et ne lèvent plus ue_failed ; le film en cours continue. La propriété is_source garde son ue_failed : une propriété n'a pas de code retour. Le même film n'est pas rechargé : of_play(source) ou is_source sur le film déjà chargé le reprend où il est (ue_resumed), au lieu de le faire repartir du début ; of_seek(0) le fait repartir. Une recherche reste dans le segment de of_play_range, celle de l'utilisateur comme of_seek : Début mène au début du segment, un clic au-delà de sa fin à sa fin — avant, Début sortait de l'extrait et un clic au-delà arrêtait le film. Une entrée de liste qui ne peut pas jouer lève ue_source_changed d'abord, puis un seul ue_failed — il venait avant, et deux fois. of_stop devient une fonction : il rendait rien (subroutine), il rend 0, ou -2 quand le composant n'est pas créé — comme of_stop du navigateur web.

// Local variables
string ls_path
long ll_rc

// The film chosen by the user
ls_path = sle_film.text

// 4.0 : of_play returned 0, and an http:// address or an .avi came back later through ue_failed
// 5.0 : the refusal is a code, at once ; the reason is in of_get_last_error
ll_rc = uo_video.of_play(/*source*/ ls_path)
if ll_rc = -5 then
	MessageBox("Video", uo_video.of_get_last_error())
end if

Ce qui change sans rien demander à votre code : un marqueur atteint par une recherche EN PAUSE ne lève plus ue_marker_reached (seulement ue_seeked) ; Espace et le bouton Lecture d'un lecteur sans film ne font plus rien (ils levaient ue_failed(REASON_NO_SOURCE)) ; la langue de sous-titres choisie par l'utilisateur suit au film suivant de la liste ; une affiche http:// est refusée et is_poster se relit vide ; is_subtitles refusé se relit vide ; un sous-titre du poste introuvable lève ue_subtitles_failed(REASON_NOT_FOUND) ; le menu de vitesse se pilote au clavier et ses flèches ne changent plus le volume ; en plein écran la barre se montre au clavier ; la position retenue (ib_remember_position) ne dépend plus de l'écriture du chemin, et seuls les 200 derniers films sont gardés (une position de la 4.0 est relue une fois). Le lecteur gagne of_play(source, subtitles) (le film et SES sous-titres : posés avant un deuxième film, ils partaient avec le premier), ib_forward_seek, of_watched_ms, of_watched_percent, ue_watched_completely et ib_skip_failed — voir la page du lecteur vidéo.

La recette : rien ne refuse de compiler. Relisez le code qui attendait ue_failed après of_play pour une adresse http://, une source vide ou un .avi : il teste désormais le -5 de l'appel. Relisez aussi un bouton « Lire » qui comptait sur of_play(source) pour repartir du début : ajoutez of_seek(0).

12.17 webbrowser : un geste de l'utilisateur est demandé, une page d'of_show_html n'a pas d'adresse #

Avec ib_veto_navigation = true, ue_navigating est désormais demandé aussi pour un geste de l'utilisateur : une adresse tapée dans la barre, Ouvrir le lien du menu contextuel, une nouvelle fenêtre ouverte par un clic. En 4.0, ces trois chemins ne posaient pas la question. Seule une adresse posée par votre code n'est jamais demandée, et une redirection du serveur ne l'est pas non plus : pour une liste de serveurs qui vaut aussi pour les redirections, posez la nouvelle propriété is_allowed_hosts.

Quoi4.05.0
ue_navigating sous véto : adresse tapée, Ouvrir le lien, nouvelle fenêtrela page s'ouvrait sans questionla question est posée ; false laisse la page
is_address, la barre, ue_load_completed après of_show_htmltoute la page encodée (data:text/html;charset=utf-8,…, jusqu'à 2 Mo)""
is_title d'une page sans <title>son adresse""
of_go_back, of_go_forward, of_stopsans retourlong : 0 une fois demandé, -2 composant non créé
ib_private changé après une pageis_address, is_title, la barre et les flèches gardaient la page d'avanttout se relit vide : la vue est neuve
Entrée sur une barre d'adresse videla page devenait blancherien
Une page du site se charge, barre d'adresse affichéeRecharger reste RechargerRecharger devient Arrêter, et revient une fois la page chargée

La recette : rien ne refuse de compiler, un long ignoré compile. Un script de ue_navigating écrit pour les liens du site voit désormais aussi les adresses tapées par l'utilisateur : s'il décide sur l'adresse, qu'il compare son hôte, comme l'exemple de la page du composant — ou confiez la liste à is_allowed_hosts. Le code qui lisait as_url de ue_load_completed, ou is_address, après of_show_html reçoit une chaîne vide.

12.18 toolbar : le clic droit porte son point, un ordre du code s'annonce #

La barre d'outils rejoint la bibliothèque : le clic droit d'un outil donne son point d'écran, comme celui des arbres, des grilles et de l'onglet, et déplacer une barre par ii_band / ii_index lève ue_bar_reordered comme le geste. Deux ajouts refusent ce qu'ils acceptaient en silence, et un raccourci posé là où rien ne vit n'est plus inscrit. Elle gagne aussi is_text sur une barre, un nom pour chaque outil et chaque champ lu par un lecteur d'écran, et un clavier qui traverse les champs — voir la page de la barre d'outils.

Quoi4.05.0
ue_item_rclicked(string as_keys)(string as_keys, long al_x, long al_y) : le point en pixels d'écran ; la touche Menu et Maj+F10 le lèvent aussi, au coin bas-gauche de l'outil, et le clic droit d'un champ aussi
ii_band / ii_index qui déplacent une barreue_layout_changedue_bar_reordered, ue_layout_changed
of_add_datepicker avec une date qui n'est pas aaaa-mm-jj ("31/12/2026")0, la date affichée telle quelle-5, rien n'est ajouté
of_add_menu_separator sur une entrée qui n'a aucune sous-entrée0 : l'entrée devenait grise et ne se choisissait plus-5
is_shortcut ou of_register_shortcut sur une adresse où rien ne vit, une entrée à cascade ou le choix d'une listeinscrit : la touche était prise dans toute la fenêtrerien d'inscrit ; of_register_shortcut rend -5, of_get_last_error dit pourquoi
Ctrl+A, Ctrl+C, Ctrl+V, Ctrl+X, Ctrl+Z, Ctrl+Y dans un champ de la barrel'outil qui portait l'accord partaitle champ édite son texte
is_text d'un sélecteur de dategardé et relu, jamais affichéignoré, relit ""
// 4.0 : the right click of a tool
// ue_item_rclicked event of uo_toolbar : (string as_keys)
// 5.0 : the same script, with the screen point
// ue_item_rclicked event of uo_toolbar : (string as_keys, long al_x, long al_y)

La recette : rien ne refuse de compiler — un script de ue_item_rclicked garde as_keys. Ouvrez votre menu au point al_x, al_y (passez-le à of_show d'un contextmenu). Vérifiez qu'un script de ue_bar_reordered accepte aussi les déplacements que fait votre code, testez le code retour d'of_add_datepicker si la date vient d'un champ régional, et posez is_shortcut après l'ajout de l'outil ou de l'entrée.

12.19 Le clic droit d'un item porte son point : buttonbar, breadcrumb, chartcartesian, statusbar #

Une seule règle pour tout clic droit sur un item de la bibliothèque : l'événement reçoit la clé (ou l'adresse) de l'item, puis al_x, al_y, le point où ouvrir un menu, en pixels d'écran — le pointeur, ou, au clavier (touche Menu, Maj+F10), le coin bas-gauche de l'item (bas-droit en lecture de droite à gauche ; le milieu d'une forme qui n'est pas un rectangle : un point de graphique). Un contextmenu de la bibliothèque s'y ouvre tel quel : uo_menu.of_show(al_x, al_y). Trois événements qui ne le portaient pas le reçoivent ; la barre d'état multipliait le sien par l'échelle de l'écran, et un menu ouvert à ce point tombait loin du pointeur sur un écran à 125 % ou 150 %.

Quoi4.05.0
buttonbar · ue_button_rclicked(string as_key)(string as_key, long al_x, long al_y)
breadcrumb · ue_item_rclicked(string as_keys)(string as_keys, long al_x, long al_y)
chartcartesian · ue_point_rclicked(string as_key, long al_index, double ad_value)(string as_key, long al_index, double ad_value, long al_x, long al_y)
statusbar · al_x, al_y de ue_panel_rclickedmultipliés par l'échelle de l'écranle point tel que la page le lit, comme tous les clics droits
// 5.0 : the menu of a button, opened where the user right-clicked it
// ue_button_rclicked event of uo_buttons : (string as_key, long al_x, long al_y)
is_menu_button = as_key
uo_menu.of_show(/*x*/ al_x, /*y*/ al_y)

La recette : rien ne refuse de compiler — un script de ces événements garde ses arguments. Ouvrez votre menu au point al_x, al_y (passez-le à of_show d'un contextmenu) ; un menu PowerBuilder garde PopMenu(PointerX(), PointerY()) de votre fenêtre. Un script qui corrigeait lui-même l'échelle des coordonnées de ue_panel_rclicked ne doit plus le faire.

12.20 Le socle : l'erreur d'un composant est la sienne, chaque verbe rend un code #

Cinq changements touchent toute la bibliothèque, ou toute une famille de composants. Un seul refuse de compiler : is_last_error d'un composant non visuel, devenu of_get_last_error().

Quoi4.05.0
of_get_last_error() d'un composant visuelle dernier message de la DLL, un seul pour tout le processus — souvent celui d'un autre composantce qui est arrivé à ce composant : un nom refusé, ou un appel de ce composant à la DLL, dont la raison est lue au moment de l'échec ; vide sinon
La raison d'un échec d'un non visuel (crypto, restclient, soundplayer, speechout, xml, u_pbt_regex, u_pbt_zip)inv.is_last_errorinv.of_get_last_error()
of_stop, of_close, of_reset des non visuels (commandpalette, crypto, messagebox, restclient, soundplayer, speechout, toaster, xml)sans valeur de retourun long, 0 une fois fait — comme les composants visuels
of_set_property("tooltip", …) et super_tooltip_* sur un composant sans info-bulle (webbrowser, pdfviewer, radialmenu, progressbar)posait une info-bulle que la doc dit inexistante-5, et of_get_last_error() dit pourquoi
Le raccourci d'un menu PowerBuilder repris (of_load_menu de menubar et de commandpalette)Ctrl++, PageUp, Insert (menubar) ; rien au-delà de F12 (palette)une seule écriture, celle du contextmenu : Ctrl+Plus, PgUp, Ins, F13 à F24, Num 0 à Num 9, Num +
// Local variables
string ls_why

// 4.0 : ls_why = inv_crypto.is_last_error
// 5.0 : the reason of a failure, by the same method as every component
ls_why = inv_crypto.of_get_last_error()

La recette : le compilateur montre chaque .is_last_error à remplacer par .of_get_last_error(). Un appel à of_stop, of_close ou of_reset écrit comme une instruction compile toujours. Un script qui lisait of_get_last_error() d'un composant pour connaître l'échec d'un autre appel (un export de la DLL appelé directement, un autre composant) lit désormais la raison de ce composant-là, ou rien : demandez-la à celui qui a échoué.

Ajouté, sans rien à reprendre : is_accessible_name et is_accessible_description sur tous les composants visuels — le nom et la description que dit un lecteur d'écran (3.4) ; of_from_datastore d'un DataWindow ou d'un DataWindowChild sur crosstab et datagrid, comme sur les autres composants liés à des données ; la forme complète d'of_insert_command (commandpalette), qui prend l'indication, le raccourci et les mots-clés comme of_add_command, avec une position en long.


← Migrer de la 3.0 à la 4.0 · Sommaire · Notes de version →