PBToolboxAI v1 ← Site

3. Base comune u_pbt_base #

← Primi passi · Sommario · Temi →


Tutti i componenti visivi ereditano da u_pbt_base, che fornisce il ciclo di vita, il motore delle proprietà, il trasporto verso il componente web e la gestione degli errori. Le proprietà vere e proprie — tema e tooltip compresi — sono pubblicate da ogni componente: la pagina del componente ne riporta l'elenco completo. Non si utilizza mai u_pbt_base direttamente — si posiziona un componente concreto — ma tutto quanto segue è disponibile ovunque.


3.1 Il motore delle proprietà #

Assegnare #

Ogni valore pilotabile è una variabile di istanza pubblica, assegnata direttamente:

uo_progress.id_value   = 42.5
uo_progress.is_label   = "Importazione in corso…"
uo_progress.ib_animated = true

Il prefisso ungherese indica il tipo: is_ string, ib_ boolean, ii_ integer, il_ long (spesso un colore RGB()), id_ double.

Non esiste alcun of_set_xxx scalare: una proprietà si imposta per assegnazione. Restano metodi le aggiunte, le rimozioni e le azioni (of_add_*, of_remove_*, of_select_*, of_reset, of_set_layout…).

Rileggere #

La lettura restituisce l'ultimo valore impostato (cache sul lato PowerBuilder):

if uo_progress.id_value >= 100 then …

Un componente web non può essere interrogato in modo sincrono: questa cache viene quindi aggiornata dagli event. Ogni volta che il componente sposta da sé una proprietà — l'utente segue un collegamento, ingrandisce con la rotellina, riduce la barra multifunzione, digita del testo — l'event che vi avvisa aggiorna la proprietà per strada. La rilettura restituisce allora lo stato reale, e il nuovo valore è già presente quando viene eseguito il codice dell'event.

Lo stesso vale per gli item : dopo un clic dell'utente, of_item(...) rilegge ciò che è a schermo — la voce selezionata, la sezione ridotta, il pulsante spuntato.

Una proprietà che nessun event accompagna, invece, resta sull'ultimo valore impostato da voi.

Raggruppare le modifiche #

Una raffica di assegnazioni provoca altrettanti rendering. of_set_redraw le fonde in uno solo:

uo_grid.of_set_redraw(false)
… venti assegnazioni e of_add_* …
uo_grid.of_set_redraw(true)     // UN solo ridisegno

Richiamare sempre entrambi (il true finale non è facoltativo).


3.2 Gli item #

Un componente con contenuto (schede, pulsanti, pannelli, riquadri, sezioni…) espone i propri elementi tramite handle tipizzati, ottenuti dal componente stesso o dal loro elemento padre.

Aggiungere #

L'aggiunta restituisce l'handle dell'elemento creato:

n_pbt_tab_page lnv_page

uo_tab.of_add_page("clients", "Clienti", uo_page_clients)
lnv_page = uo_tab.of_item("clients")
lnv_page.is_icon = "img\clients.png"

Recuperare e modificare #

of_item(id) — oppure la factory del livello interessato — restituisce l'handle di un elemento esistente; le sue proprietà si impostano esattamente come quelle di un componente:

uo_toolbar.of_bar("main").of_item("save").ib_enabled = false
uo_tab.of_item("clients").is_title = "Clienti (128)"

Gerarchie: un identificatore è univoco solo all'interno del proprio elemento padre #

Un componente a più livelli non espone alcuna scorciatoia verso la foglia: il percorso completo è obbligatorio, il che garantisce che nessun identificatore sia ambiguo.

// Barra multifunzione: scheda > gruppo > controllo > voce di menu
uo_ribbon.of_tab("home").of_group("clipboard").of_item("paste").ib_enabled = false

Anche gli event portano con sé il percorso completo:

// event ue_clicked di uo_toolbar: (string as_bar, string as_id)
choose case as_bar + "/" + as_id
    case "main/save" ; of_enregistrer()
end choose

Event degli item #

Non esistono event degli item generici sull'antenato: un identificatore di foglia da solo sarebbe ambiguo non appena gli item sono annidati (una toolbar ha più barre, un tilesbox più gruppi…). Ogni componente dichiara quindi i propri event degli item, con il percorso completo: ue_item_selected (as_section, as_id) per la listbar, ue_tile_clicked (as_group, as_id) per il tilesbox, ue_clicked (as_bar, as_id) per la toolbar…

Consultare la pagina del componente: lì si trova l'elenco esatto.


3.3 Event comuni a tutti i componenti #

EventAttivato quando
ue_ready ( )Il componente ha terminato il caricamento; tutto ciò che è stato inviato prima è stato riprodotto
ue_runtime_missing ( )Il runtime WebView2 è assente — vedere Installazione
ue_bg_color (long al_color)Il componente ha calcolato il colore di sfondo del proprio tema; l'userobject ha già adottato questo colore (backcolor), spetta a Lei adeguare la finestra se necessario

I comandi inviati prima di ue_ready non vanno perduti: vengono messi in coda e riprodotti nell'ordine. È quindi possibile configurare tutto già nel constructor o nell'open.

// event ue_bg_color: adeguare la finestra allo sfondo del componente
parent.backcolor = al_color

3.4 Proprietà ed event opzionali (opt-in) #

Alcune funzionalità non sono attive per impostazione predefinita: vengono pubblicate solo dai componenti in cui hanno un senso ed è necessario richiederle.

Altezza automatica — ib_auto_height #

Il componente misura la propria altezza ideale e ridimensiona l'userobject; l'event ue_auto_height(al_height) consente di riposizionare i controlli adiacenti.

uo_entete.ib_auto_height = true
// event ue_auto_height di uo_entete
il_hauteur_entete = al_height
of_relayout()          // riposiziona il contenuto al di sotto

Pubblicata da: picture e statictext.

Le bande non pubblicano questa proprietà: la loro altezza è intrinseca. ribbon e toolbar non scorrono verticalmente: un'altezza fissa può solo produrre spazio vuoto sotto la banda oppure contenuto troncato (barra multifunzione compressa, barra degli strumenti passata su due righe…). Si adattano quindi sempre, senza nulla da attivare, e pubblicano comunque ue_auto_height affinché Lei possa riposizionare ciò che si trova al di sotto.

Larghezza automatica — ib_auto_width #

Stesso principio per la larghezza. Pubblicata unicamente da listbar, l'unico componente la cui larghezza naturale abbia un senso.

Una listbar compressa in barra di sole icone si restringe da sola e restituisce la larghezza quando viene espansa: ib_auto_width Le serve soltanto se desidera seguire anche la larghezza espansa (la barra si allinea allora all'etichetta più lunga).

Event del mouse ambientali — ib_track_mouse #

Gli event del mouse ad alta frequenza sono interrotti alla fonte: senza sottoscrizione, il componente non li emette affatto (nulla attraversa il ponte verso PowerBuilder).

uo_bouton.ib_track_mouse = true    // attiva ue_mouse_enter / ue_mouse_leave / ue_rclicked

Pubblicati da: button, picture, statictext.

Gli event discreti (clic, selezione, menu, rilascio…) vengono sempre emessi, senza sottoscrizione.


3.5 Le scorciatoie da tastiera #

Una scorciatoia attiva un componente ovunque si trovi il focus nella finestra: l'utente non deve tornare sul pulsante per azionarlo. Ogni componente visivo le accetta, senza nulla da attivare.

uo_enregistrer.of_register_shortcut("Ctrl+S")
uo_actualiser.of_register_shortcut("F5")

Scrivere una combinazione di tasti #

La combinazione è una stringa libera, normalizzata dalla libreria: maiuscole/minuscole, spazi e ordine dei modificatori non hanno alcuna importanza. "Ctrl+Shift+S", "ctrl + shift + s" e "SHIFT+CTRL+S" indicano la stessa scorciatoia: è impossibile registrarne due varianti per sbaglio.

ElementoForme accettate
ModificatoriCtrl (o Control), Alt, Shift — combinabili, in qualsiasi ordine
Tastouna lettera AZ, una cifra 09, F1F24, Enter (o Return), Escape (o Esc), Delete (o Del), Insert, Home, End, PageUp, PageDown

Questo elenco è esaustivo: un tasto assente (Tab, Barra spaziatrice, un tasto del tastierino numerico, un segno di punteggiatura) non attiva alcuna scorciatoia.

Un tasto singolo è una combinazione valida ("F5"). Una stringa vuota rimuove la scorciatoia dal componente.

"Enter" ed "Escape" da soli non si registrano come scorciatoie: questi due tasti restano riservati al pulsante predefinito e al pulsante di annullamento (ib_default / ib_cancel del button). Combinati con un modificatore, tornano a essere combinazioni ordinarie ("Ctrl+Enter").

Chi vince in caso di conflitto #

Due componenti possono richiedere la stessa combinazione: succede spesso quando una finestra ospita più zone che hanno ciascuna il proprio « Salva ». L'arbitraggio segue questo ordine:

  1. il componente che ha il focus da tastiera prevale su tutti gli altri: la scorciatoia di una zona attiva non viene mai oscurata da un vicino;
  2. altrimenti vince il primo registrato.

Concorrono solo i componenti visibili e attivi della finestra in primo piano. Registrare di nuovo una combinazione su un componente che ne aveva già una la sostituisce senza cambiarne il rango: riconfigurare una finestra non rimescola le priorità.

Scorciatoie di item #

L'overload a due argomenti collega la combinazione a un item del componente anziché al componente intero: il secondo argomento è l'identificatore dell'item:

uo_barre.of_register_shortcut(/*combinazione*/ "Ctrl+N", /*item*/ "nouveau")
uo_barre.of_register_shortcut(/*combinazione*/ "Ctrl+P", /*item*/ "imprimer")

Rimuovere le scorciatoie #

uo_barre.of_clear_shortcuts()      // componente E item

of_reset() e la distruzione del componente richiamano of_clear_shortcuts() al posto suo: un componente scomparso non trattiene mai una combinazione riservata.

Il tasto Alt #

Alt da solo non viene catturato: dà il focus alla barra multifunzione, che mostra i propri keytip (vedere ribbon). La libreria non intercetta quindi le pressioni successive: è la barra multifunzione a leggerle, come se l'utente l'avesse cliccata. Esc o un secondo Alt restituiscono il focus al controllo abbandonato. Se nessuna barra multifunzione della finestra dichiara un keytip, Alt conserva il suo consueto comportamento Windows.

MembroEffetto
of_register_shortcut (string as_chord)Dichiara una scorciatoia per il componente; una stringa vuota la rimuove
of_register_shortcut (string as_chord, string as_key)Dichiara una scorciatoia per un item, indicato dal suo identificatore
of_clear_shortcuts ( )Rimuove tutte le scorciatoie del componente, item compresi

3.6 Riportare un componente a zero: of_reset() #

of_reset() riporta il componente al suo stato iniziale, come se fosse appena stato caricato:

uo_grid.of_reset()          // ripartire da una griglia vuota
// ... e poi ricostruire

⚠️ Riutilizzare un'istanza per visualizzare altro senza richiamare of_reset() conserva lo stato precedente (un colore, una modalità, un'altezza automatica). È la causa più frequente di un « residuo di visualizzazione » inspiegabile.


3.7 Diagnostica #

MembroEffetto
of_is_created ( ) → booleanIl componente nativo esiste (runtime presente, host valido)
of_is_ready ( ) → booleanIl contenuto web è caricato (ue_ready già attivato)
of_get_last_error ( ) → stringUltimo messaggio di errore dettagliato della DLL, dopo un valore restituito < 0

Codici restituiti dai metodi of_*:

Valore restituitoSignificato
≥ 0OK (applicato o messo in coda)
-2Componente non creato (runtime assente, host non valido)
-4Operazione non riuscita (schermata, scrittura di file…)
-5Argomento non valido (identificatore vuoto, valore fuori intervallo)
-6Runtime WebView2 troppo vecchio per la funzione richiesta (stampa)

3.8 Esportare il rendering come immagine #

Ogni componente sa esportarsi come immagine, così come viene visualizzato:

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

Per stamparlo anziché esportarlo, veda Stampare.

Utile per un report, un allegato di posta elettronica o la traccia di un incidente. Il componente deve essere creato e il suo contenuto caricato.


3.9 Ciclo di vita #

  1. Costruzione: la webview viene creata già alla costruzione dell'userobject — indispensabile per l'hosting (schede, pannelli ancorabili): una webview creata dopo il reparenting del proprio HWND non viene visualizzata.
  2. Coda di attesa: i comandi vengono messi in coda finché ue_ready non è attivato.
  3. Pronto: ue_ready; la coda viene riprodotta nell'ordine.
  4. Ridimensionamento: automatico, il componente segue la dimensione dell'userobject.
  5. Distruzione: alla chiusura della finestra; la webview viene rilasciata, senza alcun processo orfano.

Richiami PBT_Warmup() una volta all'avvio dell'applicazione affinché questo ciclo risulti impercettibile (Installazione).


3.10 Buone pratiche #


← Primi passi · Sommario · Temi →