# 6. Funzioni trasversali #

← Lingua e RTL · Sommario · FAQ →

Questo capitolo raccoglie i servizi disponibili qualunque sia il componente: tooltip, hosting di controlli PowerBuilder, trascinamento dall'Esplora risorse, focus da tastiera, esportazione immagine e gli oggetti di utilità non visivi.

## 6.1 Tooltip semplici e avanzati #

### Tooltip del componente #

    uo_bouton.is_tooltip = "Salva la pratica (Ctrl+S)"

Il testo accetta il testo formattato con tag: `[b]`, `[br]`, `[color=…]`, `[picture=…]`…

### Tooltip avanzato (titolo + testo + immagine) #

Per una guida contestuale in stile barra multifunzione di Office:

    uo_bouton.is_super_tooltip_title = "Salva"
    uo_bouton.is_super_tooltip_text  = "Scrive le modifiche sul server." &
                                       + "[br][br][size-=15]Scorciatoia: Ctrl+S[/size-=15]"
    uo_bouton.is_super_tooltip_image = "img\help_save.png"

Le tre proprietà sono indipendenti: un titolo da solo, oppure un titolo con testo senza immagine, sono validi. Non appena una proprietà `is_super_tooltip_*` viene impostata, questa prevale su `is_tooltip`.

### Tooltip di un item #

Ogni classe degli item (`n_pbt_item` e i suoi discendenti) porta le stesse quattro proprietà:

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

    uo_tab.of_item("clients").is_super_tooltip_title = "Clienti"
    uo_tab.of_item("clients").is_super_tooltip_text  = "128 schede, ultima sincronizzazione alle 09:12"

### Comportamento #

- Il tooltip è una finestra nativa a tema, identica in tutti i componenti (non è limitata dai confini della webview).
- Non compare se la Sua applicazione non ha il focus: passare con il mouse sopra una finestra in secondo piano non attiva nulla.
- Scompare quando si passa a un'altra applicazione, e al più tardi dopo 10 secondi.
- `of_reset()` elimina i tooltip impostati sull'istanza e sui suoi item.

## 6.2 Ospitare veri controlli PowerBuilder #

I componenti contenitori non mostrano HTML al posto delle Sue maschere: accolgono veri controlli PowerBuilder (userobject, DataWindow, gruppi di controlli), riagganciati come finestre Win32 figlie. Le Sue maschere esistenti vengono riutilizzate così come sono.

    // Schede: ogni pagina e' un userobject PB
    uo_tab.of_add_page("clients",   "Clienti",   uo_page_clients)
    uo_tab.of_add_page("factures",  "Fatture",  uo_page_factures, /*chiudibile*/ true)

    // Pannelli ancorabili: allo stesso modo
    uo_dock.is_main = "doc"                       // zona centrale
    uo_dock.of_add_panel("doc",      uo_dock.POSITION_STACK, "", 0,   "Documento",    uo_editeur)
    uo_dock.of_add_panel("explorer", uo_dock.POSITION_START, "", 240, "Esplora risorse", uo_arbre)
    uo_dock.of_add_panel("props",    uo_dock.POSITION_END,   "", 260, "Proprietà",  uo_props)

Ciò di cui ci occupiamo al Suo posto:

- il posizionamento e il ridimensionamento del controllo ospitato quando la scheda o il pannello cambia dimensione;
- la visualizzazione / il nascondimento al cambio di scheda o di pannello attivo;
- i pannelli mobili, ancorati o nascosti automaticamente (dockcontainer);
- la distruzione pulita alla chiusura della finestra.

> ⚠️ Un controllo ospitato è una finestra nativa: viene disegnato al di sopra dello strato web. È voluto (la Sua DataWindow resta nitida e veloce), ma significa che nessun effetto web — ombra, trasparenza, animazione — può passare sopra di esso.

## 6.3 Ricevere file dall'Esplora risorse di Windows #

Un componente può diventare destinazione di rilascio per i file trascinati dall'Esplora risorse. La libreria installa una destinazione di rilascio nativa: si ricevono i percorsi completi, cosa che un rilascio HTML non consente.

    uo_editeur.ib_allow_drop = true

    // event ue_drop_files di uo_editeur: (string as_files[])
    long ll_i

    for ll_i = 1 to UpperBound(as_files)
        of_ouvrir_fichier(as_files[ll_i])
    next

Event | Attivato quando
--- | ---
`ue_drag_enter ( )` | Un trascinamento di file entra nel componente
`ue_drag_leave ( )` | Ne esce senza rilasciare
`ue_drop_files (string as_files[])` | I file vengono rilasciati — percorsi completi

Il componente fornisce da sé il riscontro visivo del passaggio del mouse (evidenziazione della zona di rilascio). Pubblicato dai componenti in cui il rilascio ha senso: `statictext`, `codeeditor`.

## 6.4 Tastiera e focus #

Un componente PBToolboxAI partecipa alla navigazione da tastiera della Sua finestra come un controllo nativo:

- il tasto Tab lo raggiunge nell'ordine di tabulazione della finestra;
- i tasti (frecce, Invio, Esc, immissione) sono gestiti dal componente che ha il focus;
- le scorciatoie di finestra (Invio = pulsante predefinito, Esc = annulla) continuano a funzionare anche quando il focus è dentro un componente.

Per dare esplicitamente il focus al contenuto di un componente (per esempio dopo aver aperto un pannello di ricerca):

    uo_editeur.of_focus_webview()

## 6.5 Esportare il rendering come immagine #

Un promemoria dalla base comune: ogni componente si esporta così come è visualizzato.

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

Utile per allegare un grafico a un'e-mail, alimentare un report o documentare un incidente utente.

## 6.6 Finestre di dialogo e notifiche #

Due servizi senza alcun controllo da posizionare nella finestra:

    // Finestra di dialogo modale a tema (ritorno sincrono)
    n_pbt_messagebox lnv_mb

    lnv_mb = create n_pbt_messagebox
    lnv_mb.is_title   = "Eliminazione"
    lnv_mb.is_message = "Eliminare definitivamente [b]12 pratiche[/b]?"
    lnv_mb.is_icon    = lnv_mb.ICON_QUESTION
    lnv_mb.of_add_button("Elimina", /*predefinito*/ false, /*annullamento*/ false)
    lnv_mb.of_add_button("Annulla",   /*predefinito*/ true,  /*annullamento*/ true)

    if lnv_mb.of_show(Handle(this)) = 1 then of_supprimer()
    destroy lnv_mb

    // Notifica "toast" in un angolo dello schermo, non bloccante
    n_pbt_toaster lnv_toast

    lnv_toast = create n_pbt_toaster
    lnv_toast.is_title = "Importazione completata"
    lnv_toast.is_text  = "1 240 righe integrate."
    lnv_toast.is_kind  = lnv_toast.KIND_SUCCESS
    lnv_toast.of_show()
    destroy lnv_toast

Dettagli completi: messagebox e toaster.

## 6.7 Oggetti di utilità non visivi #

Forniti nella stessa PBL, senza webview né rendering: sono semplici involucri attorno alla DLL. Li crei, li usi, li distrugga.

### Codifica Base64 — `u_pbt_base64` #

    u_pbt_base64 lnv_b64
    string ls_encode

    lnv_b64 = create u_pbt_base64
    ls_encode = lnv_b64.of_encode("Buongiorno")  // testo -> UTF-8 -> Base64
    ls_texte  = lnv_b64.of_decode(ls_encode)     // "" se l'ingresso non e' valido
    destroy lnv_b64

### Impronte — `u_pbt_hash` #

    u_pbt_hash lnv_hash

    lnv_hash = create u_pbt_hash
    ls_empreinte = lnv_hash.of_sha256("password")                // esadecimale minuscolo
    ls_fichier   = lnv_hash.of_file("SHA256", "C:\livraison.zip")
    destroy lnv_hash

Metodo | Ruolo
--- | ---
`of_string (string as_algo, string as_texte)` | Impronta di una stringa — `MD5`, `SHA1`, `SHA256`, `SHA384`, `SHA512`
`of_file (string as_algo, string as_chemin)` | Impronta del contenuto di un file (`""` se illeggibile)
`of_md5` · `of_sha1` · `of_sha256` · `of_sha512` | Scorciatoie

### Espressioni regolari — `u_pbt_regex` #

Sintassi ECMAScript, assente da PowerScript.

    u_pbt_regex lnv_re
    string ls_trouves[]

    lnv_re = create u_pbt_regex

    if lnv_re.of_is_match("^[\w.]+@[\w.]+\.\w{2,}$", ls_email) then …

    ls_annee = lnv_re.of_match("(\d{4})-(\d{2})-(\d{2})", ls_date, /*gruppo*/ 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

Metodo | Ruolo
--- | ---
`of_is_match (motivo, testo [, ab_ignore_case | al_flags])` | Il testo corrisponde?
`of_match (motivo, testo, ai_groupe [, al_flags])` | Prima corrispondenza (`0` = tutto, `1..` = gruppo di cattura)
`of_match_all (motivo, testo [, ai_groupe, al_flags], ref as_res[])` | Tutte le corrispondenze; restituisce il numero
`of_replace (motivo, testo, sostituzione)` | Sostituisce tutte le occorrenze (`$1`… ammessi)

Opzioni combinabili: `FLAG_IGNORE_CASE` (1), `FLAG_SINGLELINE` (2, il `.` attraversa le interruzioni di riga).

### Identificatori univoci — `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

### Archivi ZIP — `u_pbt_zip` #

    u_pbt_zip lnv_zip

    lnv_zip = create u_pbt_zip
    lnv_zip.of_compress("C:\temp\livraison.zip", "C:\appli\export")   // file OPPURE cartella
    lnv_zip.of_extract("C:\temp\livraison.zip",  "C:\appli\import")   // cartella creata se assente
    destroy lnv_zip

I due metodi restituiscono un `boolean`.

## 6.8 Informazioni sulla libreria #

    // Versione della DLL
    string ls_version

    ls_version = Space(32)
    PBT_GetVersion(ls_version, 32)

Funzione globale | Ruolo
--- | ---
`PBT_GetVersion (ref string, long)` | Versione della libreria
`PBT_CheckRuntime (ref string, long)` | Versione del runtime WebView2 installato (`≤ 0` = assente)
`PBT_GetLastErrorMessage (ref string, long)` | Ultimo messaggio di errore del processo
`PBT_LicenseStatus ( )` | Stato della licenza — vedere Licenza

## 6.9 Stampare #

Ogni componente sa stamparsi, così com'è visualizzato, senza DataWindow intermedia.

    // Silenzioso: un PDF su disco, nulla da cliccare
    uo_grille.of_print_to_pdf("C:\etats\ventes.pdf")

    // Orizzontale, per una griglia larga
    uo_grille.of_print_to_pdf(/*fichier*/ "C:\etats\ventes.pdf", /*paysage*/ true)

    // Con finestra di dialogo: l'utente sceglie la stampante e vede l'anteprima
    uo_grille.of_print()

    // Direttamente la finestra di stampa di sistema
    uo_grille.of_print(/*dialogue systeme*/ true)

Metodo | Ruolo
--- | ---
`of_print_to_pdf (string as_path)` · `of_print_to_pdf (string, boolean ab_landscape)` | Scrive un PDF senza mostrare nulla. Restituisce solo quando il file è scritto (`0` = fatto)
`of_print ( )` · `of_print (boolean ab_system_dialog)` | Apre la finestra di stampa. Restituisce non appena la finestra è aperta: ciò che l'utente ne fa spetta a lui

> ⚠️ Si stampa ciò che è RESO. Una griglia virtualizzata stampa solo le righe che detiene: per un rapporto completo, passi prima a una disposizione che le mostri tutte (paginazione), oppure esporti i dati anziché il rendering.

Il codice di ritorno `-6` segnala un runtime WebView2 troppo vecchio per stampare (1.0.1108 per il PDF, 1.0.1587 per la finestra). Tutto il resto segue i codici di ritorno comuni.

← Lingua e RTL · Sommario · FAQ →