PBToolboxAI v1 ← Site

6. Cross-cutting features #

← Language and RTL · Contents · FAQ →


This chapter covers the services available whatever the component: tooltips, hosting PowerBuilder controls, drag and drop from Windows Explorer, keyboard focus, image export, and the non-visual utility objects.


6.1 Simple and rich tooltips #

Component tooltip #

uo_bouton.is_tooltip = "Save the file (Ctrl+S)"

The text accepts rich text markup: [b], [br], [color=…], [picture=…]

Rich tooltip (title + text + image) #

For Office ribbon style contextual help:

uo_bouton.is_super_tooltip_title = "Save"
uo_bouton.is_super_tooltip_text  = "Writes your changes to the server." &
                                   + "[br][br][size-=15]Shortcut: Ctrl+S[/size-=15]"
uo_bouton.is_super_tooltip_image = "img\help_save.png"

The three properties are independent: a title alone, or a title plus text with no image, are both valid. As soon as one is_super_tooltip_* property is set, it takes precedence over is_tooltip.

Item tooltip #

Every item class (n_pbt_item and its descendants) carries the same four properties:

uo_toolbar.of_bar("main").of_item("save").is_tooltip = "Save"

uo_tab.of_item("clients").is_super_tooltip_title = "Customers"
uo_tab.of_item("clients").is_super_tooltip_text  = "128 records, last synced at 09:12"

Behavior #


6.2 Hosting real PowerBuilder controls #

Container components do not display HTML in place of your screens: they host real PowerBuilder controls (userobjects, DataWindows, control groups), reparented as Win32 child windows. Your existing screens are reused as they are.

// Tabs: each page is a PB userobject
uo_tab.of_add_page("clients",   "Customers",   uo_page_clients)
uo_tab.of_add_page("factures",  "Invoices",  uo_page_factures, /*closable*/ true)

// Dockable panels: same principle
uo_dock.is_main = "doc"                       // center area
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, "Explorer", uo_arbre)
uo_dock.of_add_panel("props",    uo_dock.POSITION_END,   "", 260, "Properties",  uo_props)

What is handled for you:

⚠️ A hosted control is a native window: it is painted on top of the web layer. That is by design (your DataWindow stays crisp and fast), but it means no web effect — shadow, transparency, animation — can be drawn over it.


6.3 Receiving files from Windows Explorer #

A component can become a drop target for files dragged from Windows Explorer. The library installs a native drop target: you receive the full paths, which an HTML drop cannot give you.

uo_editeur.ib_allow_drop = true
// ue_drop_files event of uo_editeur: (string as_files[])
long ll_i

for ll_i = 1 to UpperBound(as_files)
    of_ouvrir_fichier(as_files[ll_i])
next
EventRaised when
ue_drag_enter ( )A file drag enters the component
ue_drag_leave ( )It leaves without dropping
ue_drop_files (string as_files[])The files are dropped — full paths

The component provides the hover visual feedback itself (the drop zone is highlighted). Published by the components where dropping makes sense: statictext, codeeditor.


6.4 Keyboard and focus #

A PBToolboxAI component takes part in the keyboard navigation of your window just like a native control:

To explicitly give the focus to a component's content (for example after opening a search panel):

uo_editeur.of_focus_webview()

6.5 Exporting the rendering as an image #

A reminder from the shared foundation: every component can be exported exactly as displayed.

uo_pivot.of_save_as_png("C:\temp\tableau.png")
uo_pivot.of_save_as_jpg("C:\temp\tableau.jpg")

Handy for attaching a chart to an email, feeding a report, or documenting a user incident.


6.6 Dialog boxes and notifications #

Two services that require no control on the window:

// Themed modal dialog box (synchronous return)
n_pbt_messagebox lnv_mb

lnv_mb = create n_pbt_messagebox
lnv_mb.is_title   = "Delete"
lnv_mb.is_message = "Permanently delete [b]12 files[/b]?"
lnv_mb.is_icon    = lnv_mb.ICON_QUESTION
lnv_mb.of_add_button("Delete", /*default*/ false, /*cancel*/ false)
lnv_mb.of_add_button("Cancel",   /*default*/ true,  /*cancel*/ true)

if lnv_mb.of_show(Handle(this)) = 1 then of_supprimer()
destroy lnv_mb
// Non-blocking "toast" notification in a screen corner
n_pbt_toaster lnv_toast

lnv_toast = create n_pbt_toaster
lnv_toast.is_title = "Import complete"
lnv_toast.is_text  = "1,240 rows imported."
lnv_toast.is_kind  = lnv_toast.KIND_SUCCESS
lnv_toast.of_show()
destroy lnv_toast

Full details: messagebox and toaster.


6.7 Non-visual utility objects #

Shipped in the same PBL, with no webview and no rendering: they are simple wrappers around the DLL. Create them, use them, destroy them.

Base64 encoding — u_pbt_base64 #

u_pbt_base64 lnv_b64
string ls_encode

lnv_b64 = create u_pbt_base64
ls_encode = lnv_b64.of_encode("Hello")       // text -> UTF-8 -> Base64
ls_texte  = lnv_b64.of_decode(ls_encode)     // "" if the input is invalid
destroy lnv_b64

Hashes — u_pbt_hash #

u_pbt_hash lnv_hash

lnv_hash = create u_pbt_hash
ls_empreinte = lnv_hash.of_sha256("password")                // lowercase hex
ls_fichier   = lnv_hash.of_file("SHA256", "C:\livraison.zip")
destroy lnv_hash
MethodPurpose
of_string (string as_algo, string as_texte)Hash of a string — MD5, SHA1, SHA256, SHA384, SHA512
of_file (string as_algo, string as_chemin)Hash of a file's contents ("" if unreadable)
of_md5 · of_sha1 · of_sha256 · of_sha512Shorthands

Regular expressions — u_pbt_regex #

ECMAScript syntax, which PowerScript does not provide.

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, /*group*/ 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
MethodPurpose
of_is_match (pattern, text [, ab_ignore_case | al_flags])Does the text match?
of_match (pattern, text, ai_groupe [, al_flags])First match (0 = whole match, 1.. = capturing group)
of_match_all (pattern, text [, ai_groupe, al_flags], ref as_res[])All matches; returns the count
of_replace (pattern, text, replacement)Replaces every occurrence ($1… allowed)

Options can be combined: FLAG_IGNORE_CASE (1), FLAG_SINGLELINE (2, . also matches line breaks).

Unique identifiers — 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

ZIP archives — 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")   // file OR folder
lnv_zip.of_extract("C:\temp\livraison.zip",  "C:\appli\import")   // folder created if missing
destroy lnv_zip

Both methods return a boolean.


6.8 Library information #

// DLL version
string ls_version

ls_version = Space(32)
PBT_GetVersion(ls_version, 32)
Global functionPurpose
PBT_GetVersion (ref string, long)Library version
PBT_CheckRuntime (ref string, long)Version of the installed WebView2 runtime (≤ 0 = missing)
PBT_GetLastErrorMessage (ref string, long)Last error message for the process
PBT_LicenseStatus ( )License state — see License

6.9 Printing #

Every component knows how to print itself, as displayed, with no intermediate DataWindow.

// Silent: a PDF on disk, nothing to click
uo_grille.of_print_to_pdf("C:\etats\ventes.pdf")

// Landscape, for a wide grid
uo_grille.of_print_to_pdf(/*fichier*/ "C:\etats\ventes.pdf", /*paysage*/ true)

// With a dialog: the user picks their printer and sees the preview
uo_grille.of_print()

// Straight to the system print dialog
uo_grille.of_print(/*dialogue systeme*/ true)
MethodPurpose
of_print_to_pdf (string as_path) · of_print_to_pdf (string, boolean ab_landscape)Writes a PDF without showing anything. Returns only once the file is written (0 = done)
of_print ( ) · of_print (boolean ab_system_dialog)Opens the print dialog. Returns as soon as the dialog is up: what the user does with it is theirs

⚠️ What is printed is what is RENDERED. A virtualized grid prints only the rows it holds: for a complete report, first switch to a layout that shows them all (pagination), or export the data rather than the rendering.

Return code -6 means the WebView2 runtime is too old to print (1.0.1108 for the PDF, 1.0.1587 for the dialog). Everything else follows the common return codes.



← Language and RTL · Contents · FAQ →