# messagebox — `n_pbt_messagebox` #

← Riferimento dei componenti · Sommario della guida

> Finestra di dialogo modale a tema, con esito sincrono: il sostituto diretto del `MessageBox()` di PowerBuilder, con testo formattato, pulsanti liberi, icone e casella di controllo.

> ▶ Vederlo dal vivo — Applicazione dimostrativa, riquadro Message box: l'anteprima, il codice che lo produce e questa pagina, affiancati.

## In breve #

Oggetto | `n_pbt_messagebox` — non visuale: nulla da collocare nella finestra
Serve per | Porre una domanda o annunciare un risultato, al posto del `MessageBox()` nativo, rigido e privo di tema
Esito | Sincrono: `of_show()` blocca e restituisce l'indice del pulsante cliccato

A differenza dei componenti visuali, questo oggetto non si inserisce in una finestra: lo si crea, configura, mostra, distrugge.

    n_pbt_messagebox lnv_mb

    lnv_mb = create n_pbt_messagebox
    // ... configurazione ...
    destroy lnv_mb

## Avvio rapido #

    n_pbt_messagebox lnv_mb

    lnv_mb = create n_pbt_messagebox

    lnv_mb.is_title   = "Eliminazione"
    lnv_mb.is_icon    = lnv_mb.ICON_WARNING
    lnv_mb.is_message = "Eliminare definitivamente [b]12 cartelle[/b] ?[br][br]Questa azione è irreversibile."

    lnv_mb.of_add_button(/*testo*/ "Elimina", /*predefinito*/ true,  /*annullamento*/ false)   // -> 1
    lnv_mb.of_add_button(/*testo*/ "Annulla",   /*predefinito*/ false, /*annullamento*/ true)    // -> 2

    if lnv_mb.of_show(/*hwnd*/ Handle(this)) = 1 then
        of_supprimer()
    end if

    destroy lnv_mb

`of_show` attende la risposta dell'utente: la riga successiva viene eseguita solo dopo il clic, esattamente come con `MessageBox()`.

## Proprietà #

Da impostare prima di `of_show`.

Proprietà | Tipo | Predefinito | Ruolo
--- | --- | --- | ---
`is_title` | string | `""` | Titolo visualizzato nell'intestazione della finestra
`is_message` | string | `""` | Corpo del messaggio. Accetta il testo formattato con tag (`[b]`, `[i]`, `[br]`, `[accent]`, `[picture=…]`…)
`is_instruction` | string | `""` | Istruzione principale: la domanda stessa, mostrata più grande sopra il messaggio. Titolo / istruzione / messaggio è l'anatomia che rende un dialogo leggibile a colpo d'occhio — «Eliminare 42 righe?» poi «L'operazione è definitiva» — invece di un blocco uniforme. Accetta la marcatura
`is_icon` | string | `""` | Icona: una costante `ICON_*`, oppure una sua immagine personale (percorso di file o risorsa di DLL `mia.dll:NOME`)
`is_checkbox` | string | `""` | Testo di una casella di controllo facoltativa, in stile «non chiedermelo più» (`""` = nessuna casella)
`ib_checked` | boolean | `false` | Stato iniziale della casella (lo stato finale si legge con `of_checked()`)
`ib_input` | boolean | `false` | Aggiunge un campo di immissione a tema (rinominare, motivo, commento), così un'applicazione non deve più costruirsi una finestra che non segue né il tema né il senso di lettura. Si rilegge con `of_input_value()` dopo `of_show`. Tutto in una chiamata: `of_prompt`
`is_input_label` | string | `""` | Etichetta sopra il campo (`""` = nessuna). Richiede `ib_input`
`is_input_value` | string | `""` | Contenuto iniziale del campo. All'apertura è selezionato: digitare lo sostituisce, come in ogni dialogo di rinomina
`is_input_placeholder` | string | `""` | Suggerimento mostrato finché il campo è vuoto. Non è un valore: se l'utente non digita nulla, nulla viene restituito
`ib_input_password` | boolean | `false` | Maschera i caratteri digitati
`ib_input_required` | boolean | `false` | Il pulsante predefinito resta disattivato finché il campo è vuoto. Lasciar inviare per poi rimproverare non serve a nessuno; il pulsante di annullamento resta raggiungibile
`ib_buttons_reverse` | boolean | `false` | Ordine dei pulsanti: `false` = da sinistra a destra nell'ordine di aggiunta; `true` = invertito
`is_position` | string | `POSITION_OWNER` | Centratura: `POSITION_OWNER` (sulla finestra chiamante) o `POSITION_SCREEN` (sullo schermo)
`il_min_width` | long | `0` | Larghezza minima in pixel (`0` = automatica)
`il_max_width` | long | `0` | Larghezza massima in pixel (`0` = automatica): il testo va a capo entro questo limite
`il_max_height` | long | `0` | Altezza massima in pixel (`0` = automatica): oltre, il corpo del messaggio scorre invece di ingrandire la finestra

### Costanti #

Costante | Valore | Uso
--- | --- | ---
`ICON_INFORMATION` | `"information"` | Informazione neutra
`ICON_WARNING` | `"warning"` | Avviso, azione rischiosa
`ICON_ERROR` | `"error"` | Insuccesso, errore
`ICON_QUESTION` | `"question"` | Domanda chiusa
`ICON_SUCCESS` | `"success"` | Conferma di un esito positivo
`ICON_NONE` | `"none"` | Nessuna icona
`POSITION_OWNER` | `"owner"` | Centrata sulla finestra chiamante
`POSITION_SCREEN` | `"screen"` | Centrata sullo schermo

## Metodi #

Metodo | Ruolo
--- | ---
`of_add_button (string as_texte)` → long | Aggiunge un pulsante semplice. Restituisce il suo indice a partire da 1
`of_add_button (string as_texte, boolean ab_defaut, boolean ab_annulation)` → long | Idem, contrassegnando il pulsante come predefinito (Invio) e/o di annullamento (Esc)
`of_add_button (string as_texte, string as_icone, boolean ab_defaut, boolean ab_annulation)` → long | Idem, con un'icona sul pulsante
`of_add_button_timed (string as_texte, boolean ab_defaut, boolean ab_annulation, long al_secondes_actif, long al_secondes_clic)` → long | Pulsante con conto alla rovescia: resta disattivato per `al_secondes_actif` secondi (contatore visibile), poi si clicca da solo dopo `al_secondes_clic` secondi (`0` = timer inattivo)
`of_show (long al_hwnd)` → long | Mostra la finestra modale e restituisce l'indice del pulsante cliccato (`0` = chiusura con Esc o con la croce senza pulsante di annullamento)
`of_checked ( )` → boolean | Stato della casella di controllo al momento dell'ultimo `of_show`
`of_input_value ( )` → string | Testo digitato nell'ultimo `of_show` (vuoto se `ib_input` era disattivo)
`of_action ( )` → string | Id della zona `[action=id]` cliccata nel messaggio, stringa vuota altrimenti. Una zona simile è una scelta offerta nella frase stessa: chiude il dialogo e `of_show` restituisce `0`. Una zona `[hyperlink=url]`, invece, si apre nel browser e lascia il dialogo aperto — il chiamante è bloccato in `of_show`, quindi un collegamento non può essere una risposta
`of_info (long al_hwnd, string as_title, string as_message)` → long | Dialogo in una riga, come lo è `MessageBox()`: icona d'informazione e un solo pulsante OK, restituisce `1`. Le etichette vengono dalle traduzioni della libreria (6 lingue) invece di essere scritte in ogni applicazione — è tutta la ragion d'essere di queste scorciatoie
`of_warning (long al_hwnd, string as_title, string as_message)` → long | Icona di avviso, un pulsante OK. Restituisce `1`
`of_error (long al_hwnd, string as_title, string as_message)` → long | Icona di errore, un pulsante OK. Restituisce `1`
`of_success (long al_hwnd, string as_title, string as_message)` → long | Icona di riuscita, un pulsante OK. Restituisce `1`
`of_confirm (long al_hwnd, string as_title, string as_message)` → long | Domanda + OK / Annulla. Restituisce `1` = OK, `2` = Annulla, `0` = chiuso
`of_yes_no (long al_hwnd, string as_title, string as_message)` → long | Domanda + Sì / No. Restituisce `1` = Sì, `2` = No, `0` = chiuso
`of_yes_no_cancel (long al_hwnd, string as_title, string as_message)` → long | Domanda + Sì / No / Annulla. Restituisce `1`, `2`, `3`, o `0` se chiuso
`of_prompt (long al_hwnd, string as_title, string as_message, string as_default)` → string | Chiede un valore e restituisce quanto digitato, o una stringa vuota se l'utente ha annullato. Per distinguere una risposta vuota da un annullamento, usi `of_show` + `of_input_value`
`of_reset ( )` | Cancella tutte le proprietà e i pulsanti aggiunti: la stessa istanza riparte da zero

L'etichetta di un pulsante accetta il testo formattato con tag e il mnemonico `&` (`"&Salva"` sottolinea la S e la attiva con `Alt+S`); `&&` mostra una e commerciale letterale.

## La tastiera #

Tasto | Effetto
--- | ---
Invio | Attiva il pulsante contrassegnato come predefinito
Esc | Attiva il pulsante contrassegnato come annullamento; senza pulsante di annullamento chiude la finestra e restituisce `0`
Alt + lettera | Attiva il pulsante la cui etichetta porta quel mnemonico
Tab | Sposta il focus da un pulsante all'altro
Ctrl + C | Copia il dialogo (titolo, istruzione, messaggio, etichette dei pulsanti) negli appunti, come ogni finestra di dialogo di Windows — comodo quando un errore va inoltrato all'assistenza

> All'apertura nessun pulsante ha un contorno di focus: è voluto, ed è il comportamento delle finestre di dialogo Windows moderne. Il bordo appare solo dopo una prima pressione di Tab, cioè quando l'utente passa esplicitamente alla tastiera. Invio ed Esc restano attivi fin dal primo secondo, anche senza focus visibile.

## Esempi #

### Domanda chiusa con pulsante predefinito #

    n_pbt_messagebox lnv_mb
    long ll_reponse

    lnv_mb = create n_pbt_messagebox

    lnv_mb.is_title   = "Salvare le modifiche"
    lnv_mb.is_icon    = lnv_mb.ICON_QUESTION
    lnv_mb.is_message = "La cartella è stata modificata. Vuole salvare prima di chiudere ?"

    lnv_mb.of_add_button(/*testo*/ "&Salva",     /*predefinito*/ true,  /*annullamento*/ false)  // 1
    lnv_mb.of_add_button(/*testo*/ "&Non salvare", /*predefinito*/ false, /*annullamento*/ false) // 2
    lnv_mb.of_add_button(/*testo*/ "Annulla",          /*predefinito*/ false, /*annullamento*/ true)   // 3

    ll_reponse = lnv_mb.of_show(/*hwnd*/ Handle(this))
    destroy lnv_mb

    choose case ll_reponse
        case 1 ; of_enregistrer() ; Close(parent)
        case 2 ; Close(parent)
        case else ; // 3 o 0 : non si chiude
    end choose

### Messaggio formattato e icona #

    lnv_mb.is_title   = "Importazione completata"
    lnv_mb.is_icon    = lnv_mb.ICON_SUCCESS
    lnv_mb.is_message = "[b]1 240 righe[/b] integrate.[br][br]" &
                      + "[accent]18 duplicati[/accent] sono stati ignorati."

    lnv_mb.of_add_button(/*testo*/ "OK", /*predefinito*/ true, /*annullamento*/ false)
    lnv_mb.of_show(/*hwnd*/ Handle(this))

### Casella «non chiedermelo più» #

    n_pbt_messagebox lnv_mb

    lnv_mb = create n_pbt_messagebox

    lnv_mb.is_title    = "Eliminazione"
    lnv_mb.is_icon     = lnv_mb.ICON_WARNING
    lnv_mb.is_message  = "Eliminare le righe selezionate ? Questa azione è irreversibile."
    lnv_mb.is_checkbox = "Non chiedermelo più"
    lnv_mb.ib_checked  = false

    lnv_mb.of_add_button(/*testo*/ "Elimina", /*predefinito*/ true,  /*annullamento*/ false)
    lnv_mb.of_add_button(/*testo*/ "Annulla",   /*predefinito*/ false, /*annullamento*/ true)

    if lnv_mb.of_show(/*hwnd*/ Handle(this)) = 1 then
        of_supprimer()
        // Memorizzare la scelta dell'utente
        ib_confirmer_suppression = not lnv_mb.of_checked()
    end if

    destroy lnv_mb

### Pulsante con conto alla rovescia #

    lnv_mb.is_title   = "Riavvio"
    lnv_mb.is_icon    = lnv_mb.ICON_INFORMATION
    lnv_mb.is_message = "L'applicazione verrà riavviata per applicare l'aggiornamento."

    // "Continua" resta disattivato 3 secondi (viene mostrato un contatore)
    lnv_mb.of_add_button_timed(/*testo*/ "Continua", /*predefinito*/ true, /*annullamento*/ false, &
                               /*secondi_attivo*/ 3, /*secondi_clic*/ 0)

    // "Piu tardi" si clicca da solo dopo 10 secondi
    lnv_mb.of_add_button_timed(/*testo*/ "Più tardi", /*predefinito*/ false, /*annullamento*/ true, &
                               /*secondi_attivo*/ 0, /*secondi_clic*/ 10)

    lnv_mb.of_show(/*hwnd*/ Handle(this))

### Messaggio lungo: limitare le dimensioni #

    // Un testo voluminoso : la finestra e limitata e il corpo scorre
    lnv_mb.is_title      = "Note di rilascio"
    lnv_mb.is_message    = ls_notes
    lnv_mb.il_max_width  = 480
    lnv_mb.il_max_height = 320

    lnv_mb.of_add_button(/*testo*/ "Chiudi", /*predefinito*/ true, /*annullamento*/ true)
    lnv_mb.of_show(/*hwnd*/ Handle(this))

### Riutilizzare un'istanza #

    // Un'istanza di finestra, piu dialoghi : of_reset tra una chiamata e l'altra
    inv_mb.of_reset()      // cancella le proprieta E i pulsanti precedenti

    inv_mb.is_title   = "Secondo dialogo"
    inv_mb.is_message = "Ogni of_reset riparte da una finestra vergine."
    inv_mb.of_add_button(/*testo*/ "OK", /*predefinito*/ true, /*annullamento*/ false)
    inv_mb.of_show(/*hwnd*/ Handle(this))

## Buone pratiche #

- Chiami sempre `of_reset()` prima di riconfigurare un'istanza riutilizzata: senza di esso i pulsanti del dialogo precedente si aggiungono ai nuovi.
- Contrassegni sistematicamente un pulsante predefinito e un pulsante di annullamento: chi usa la tastiera si aspetta Invio ed Esc.
- Verifichi il valore restituito `0`: significa che la finestra è stata chiusa senza scelta (croce o Esc). Lo tratti come un annullamento.
- Passi `Handle(this)` (o `Handle(parent)`) come finestra chiamante: la finestra si centra su di essa e la modalità riguarda la finestra giusta.
- Riservi il rosso e `ICON_ERROR` agli errori veri; una conferma banale merita `ICON_QUESTION`.
- Per un'informazione che non richiede alcuna risposta, preferisca una notifica non bloccante: vedere toaster.

← Riferimento dei componenti · Sommario della guida