Gli script di Jaws 07. La Gestione dei Dati ed il Sistema sui Controlli.

Programmiamoli da Soli!

Gli archivi testuali.

Jaws utilizza continuamente dei dati memorizzati in alcuni file speciali, che sono in realtà degli archivi testuali in formato
INI
. Tale formato, usato per la prima volta dalla Microsoft per i suoi file di configurazione, è ancora utilizzato da molti programmi che funzionano con Windows, tra i quali appunto anche Jaws.

Appare perciò indispensabile che anche noi, nelle nostre personalizzazioni, si provi ad usare questo sistema di gestione dei dati, con tutti i vantaggi che ne derivano. In particolare, registrare dei dati su disco ci consente di uscire dai limiti del singolo script, che si attiva con i tasti, compie un’azione e poi termina, inserendo i nostri lavori in veri e propri sistemi che si integrano alle normali funzioni di Jaws, a volte persino sostituendole.

Lo scorso capitolo abbiamo svolto solo la prima parte dell’opera legata ai controlli sulle finestre, proprio perché ci mancava la competenza su questo tema. Dopo aver compreso bene di cosa si tratti, ed imparato ad usare i dati come fa Jaws, proseguiremo completando il sistema dei controlli, automatizzando il più possibile la loro gestione.

Una volta implementato tale sistema, lo useremo praticamente in ogni lavoro svolto da qui in avanti. Per questo capitolo ci dedicheremo ad una prima applicazione di esempio, solo per eseguire il necessario collaudo, cogliendo comunque tutte le occasioni che ci consentiranno di proporre altre pillole di nozioni teoriche.

Prima di allora, tuttavia, ci dedichiamo alla solita breve parentesi che, ormai da un po’ di occasioni, serve ad inizializzare il lavoro di ciascun capitolo.

Esercizio 7.1.1. Aggiornare il file Personale delle Costanti.


JCF = ".JCF", ; estensione per i file configurazione delle applicazioni
PERSONALE = 2, ; valore per gli archivi personali
PS_FILE = "_PsDefault", ; file configurazione degli script personali
APP = 3, ; file Tasti dell’applicativo corrente
JKM = ".JKM", ; estensione omonima
JAWS = 4, ; file Tasti Predefinito
JAWS_FILE = "Default", ; nome dei file predefiniti di Jaws
TIPI_FINESTRE = "TipiFinestre", ; sezione con l’elenco delle finestre di cui salvare i dati
DATI_FINESTRE = "DatiFinestre", ; sezione per i dati delle finestre nei file per le applicazioni
EDITING = "Editing", ; nome assegnato ad un tipo di finestra
NESSUNO = "Nessuno", ; termine omonimo
F3 = "F3", ; combinazione tasti omologa
SHIFT_F3 = "Shift+F3", ; combinazione tasti omologa
MANAGER = "Manager", ; termine omonimo
CONTROL_FRECCIAGIU = "Control+DownArrow", ; combinazione tasti omologa
CONTROL_FRECCIASU = "Control+UpArrow", ; combinazione tasti omologa
F2 = "F2", ; tasto omonimo
SHIFT_F2 = "Shift+F2", ; combinazione tasti omologa

Esercizio 7.1.2. Aggiornare il file Personale dei Messaggi.


; esito positivo scrittura file archivio
@hlpScritturaOk
Dati salvati per %1.
@@
; esito positivo scrittura file archivio - versione corta
@hlpScritturaOk_corto
Dati salvati.
@@
; errore di scrittura sui file archivio
@hlpNoScrittura
Impossibile salvare i dati su %1.
@@
; errore di scrittura sui file archivio - versione corta
@hlpNoScrittura_corto
Dati non salvati.
@@
; messaggio di conferma all’uscita
@msgConfermaUscita
Si conferma l’uscita dalla procedura?
@@
; titolo per conferma all’uscita
@ttlConfermaUscita
Nessuna scelta effettuata.
@@
; istruzioni per l’inserimento di un testo su una singola riga
@msgInserisciRiga
Invio conferma, Esc Uscita.
@@
; titolo per l’immissione del nuovo tipo
@ttlTipoNuovoFinestra
Tipo di finestra della quale rilevare i dati.
@@
; conferma scrittura dati finestra attiva
@msgConfermaDati
Confermate l’attuale come finestra %1 per %2?
@@
; titolo per conferma scrittura dati finestra
@ttlConfermaDati
Salvataggio Dati Finestra.
@@
; Voce di scelta per immissione nuovo tipo
@lstNuovoTipo
Immetti nuovo tipo
@@
; scelta tipi finestra
@ttlTipiFinestre
Selezionare il tipo di finestra, o %1. %2
@@
; Istruzioni standard per schermata di scelta
@msgInfoScelte
Ok o Invio per conferma, Annulla o Esc per uscire.
@@
; Nessun livello impostato per la finestra specificata
@hlpNoLivello
Impostare il livello per il tipo di finestra %1.
@@
; Finestra controllata non corrispondente
@hlpNoFinestra
Finestra non valida.
@@
; Finestra controllata non corrispondente - versione corta
@hlpNoFinestra_corto
Non valida.
@@

***

Istruire Jaws.

Parlando delle informazioni che servono agli script, noi abbiamo due strade fondamentali: o lavoriamo noi, scrivendo di volta in volta dati ed informazioni che servono al codice per essere eseguito, oppure diamo tali informazioni a Jaws solo la prima volta, scrivendole nei file configurazione, e poi lasciando sia il programma di sintesi vocale che vada a leggersi le informazioni man mano che servono.

Facciamo come al solito un esempio: se vi ricordate, la condizione della struttura di controllo realizzata nello scorso capitolo, che serviva a verificare se fossimo nella finestra corretta per eseguire lo script, era la seguente:


If CodiceFinestra (CORRENTE) != CODICE_EDITOR Then

In questa istruzione, noi davamo per scontato che:

  1. La finestra da confrontare avesse i dati che noi avevamo impostato nella costante
    CODICE_EDITOR.
  2. Il livello della finestra da controllare fosse quello corrente.
  3. Il tipo di finestra da controllare fosse quello di editazione, cui sempre noi avevamo assegnato il nome di
    Editing.

Ora, se noi vogliamo automatizzare questo controllo, noi dobbiamo dare a Jaws tutte queste informazioni. La maggior parte di questi dati saranno scritti come detto nei file di configurazione, ed immessi tramite gli script che andremo a realizzare.

Questo sistema nel suo complesso, si occuperà di: dire a Jaws:

  1. Quali siano i tipi di finestre da controllare.
  2. Quale sia il livello che in ciascuna di tali finestre dovrà essere controllato.
  3. Quale sia, per ciascuna delle applicazioni di nostro interesse, la finestra corretta per ciascuno dei singoli tipi di finestra da monitorare.

Se letti così, i dati da inserire sembrerebbero tanti. In realtà il sistema prevede sia una fase di immissione dati a sé stante, eseguendo l’apposito script, sia la necessità di inserire delle informazioni anche durante il normale lavoro quotidiano. In particolare, se si esegue un qualsiasi script a cui è stato applicato il controllo, qualora un dato per il confronto non sia già stato specificato, potremo attivare una speciale modalità in cui sarà lo stesso sistema a fornircelo, registrandolo poi nel posto giusto da dove Jaws lo leggerà la volta successiva.

Come potete capire, quindi, questa fase di
apprendimento
cui sottoporremo il programma di sintesi vocale, potrebbe anche essere più semplice del previsto. Soprattutto, essa potrà essere diluita nel tempo ed attivata solo quando serve, alla prima occasione in cui utilizzeremo uno script che deve funzionare per uno specifico tipo di finestre.

Va detto che questo sistema di riconoscimento delle finestre, per dire a ciascuno script o funzione se sono al posto giusto dove operare, non solo esiste già nel codice originale, ma è di gran lunga più completo ed efficiente di quanto noi potremo mai fare. Il problema è che esso si applica solo conoscendo a fondo tutte le funzioni integrate di Jaws, inserendo dei controlli mirati e particolari per ciascun tipo di lavoro svolto. Siccome questo è un tipo di conoscenza che, non solo non abbiamo ora, ma probabilmente non avremo mai, l’unico modo che abbiamo per avere subito dei risultati concreti è quello di costruirci da soli, così come ci siamo prefissi di fare, un sistema semplificato che esegua soltanto i controlli a noi strettamente necessari.

Si cercherà come al solito di dare tutte le informazioni indispensabili, ma ci si rende anche conto che potrà lo stesso non essere semplice comprendere appieno tutti i passaggi, quello che andremo a fare da qui alla fine del capitolo. L’aspetto fondamentale è chiarire che il buon numero di elementi tra funzioni e script che andremo a realizzare, costituisce la base che renderà possibile completare il nostro viaggio nel mondo degli Script di Jaws.

Quindi, non ci resta che cominciare, partendo dal capire dove saranno memorizzati i dati di cui ci serviremo.

I file di configurazione di Jaws.

I file su cui Jaws scrive e legge i suoi dati sono molteplici, con vari tipi di nomi e di estensioni. Inizieremo con l’analizzare dei file di configurazione, i quali hanno l’estensione
JCF
. Il nome di questi file per le varie applicazioni, di solito, è lo stesso che Jaws assegna ai rispettivi file script, quando si richiama l’Editor da dentro l’applicazione stessa. Ad esempio, per
Microsoft Wordpad
, il file script è
Wordpad.JSS
e quello di configurazione si chiama
Wordpad.JCF.

Per sapere qual’è il nome che viene assegnato ai file configurazione, esiste anche una funzione integrata,
GetActiveConfiguration
, (OttieniConfigurazioneAttiva). Grazie a tale funzione noi possiamo quindi sapere quali siano, per ciascuna applicazione che sia attiva in quel momento, i file di configurazione che usa Jaws. Potremo così servirci il più possibile di tali archivi anche per le nostre registrazioni, in modo da da creare il minor numero possibile di file rispetto a quelli che Jaws già utilizzi.

Per capire come funzionano gli archivi per la registrazione dei dati, inizieremo analizzando come sono fatti. In particolare, ci occuperemo del file configurazione generale di Jaws, che si chiama
Default.JCF
, che ora andremo ad aprire.

Nel dettaglio, seguite questi passi:

  1. Dentro all’Editor di Script, premete
    Control+O
    per aprire la schermata di apertura File.
  2. Selezionate
    Tutti i file (*.*)
    , e tornate nell’elenco dei file premendo
    Shift+Tab
    tre volte.
  3. Qui premete la lettera
    D
    finché appare come selezionato il file
    Default.JCF
    , quindi premete Invio per Aprirlo.

A prescindere dal contenuto specifico, che può variare da caso a caso, esso è composto di due elementi fondamentali:

  1. Un termine racchiuso da una coppia di parentesi quadre, che indica il titolo e l’inizio di una
    sezione
    di dati.
  2. Una o più assegnazioni, con due gruppi testuali divisi tra di essi da un segno di Uguale,
    =
    . Tale segno separa la
    chiave
    , posta prima dell’Uguale, ed il
    dato
    , che si trova dopo tale carattere.

In pratica, se voi ne analizzaste l’inizio, potrete comunque rilevare lo schema seguente:


[Sezione1]
Chiave1=Dato1
chiave2=dato2
chiave3=dato3
[Sezione2]
Chiave1=Dato1
chiave2=dato2
chiave3=dato3

Questo è dunque il formato dei famosi
File INI
, di cui si accennava in precedenza. Sulla base dello schema proposto, si possono riassumere alcune regole, valide per tutti i file di questo tipo:

  1. Il nome della sezione deve essere univoco in uno stesso file, ma possono esistere un numero anche elevato di sezioni diverse.
  2. Le singole chiavi all’interno di ciascuna sezione, così come abbiamo posto nell’esempio, possono avere anche nomi uguali in sezioni diverse.
  3. All’interno di ciascuna sezione, anche se nel nostro esempio ne abbiamo usato solo tre, il numero di assegnazioni è libero.
  4. Nel caso in cui, per qualche motivo, in una sezione vi fossero presenti due dati con una chiave uguale, sarebbe ritenuta valida solo la prima occorrenza partendo dall’etichetta della sezione.
  5. Così come nei file script, il carattere Punto e Virgola posto ad inizio riga fa considerare come dei commenti l’eventuale testo posizionato alla sua destra. Se però il carattere Punto e Virgola fosse posto dopo il segno di Uguale, esso sarebbe considerato come parte del dato, e quindi non come un commento.

Al di là di queste regole, che sono comunque gestite da Jaws senza che sia necessario un nostro controllo diretto, la cosa importante è che teniate a mente questi termini:
Sezione,
chiave
e
dato
. Attorno ad essi, infatti, girerà gran parte del nostro lavoro, non solo di questo capitolo.

Ora potete anche chiudere il file configurazione predefinito,
Default.JCF
, con il comando
Control+F4.

Un’ultima informazione, sull’argomento: questi file in formato INI, come ad esempio gli
JCF
, essendo dei normalissimi file testuali, si possono aprire, oltre che con l’Editor di Script, anche con un qualsiasi editor testuale, come ad esempio il Blocco Note di Windows.

Struttura dei file con estensione JKM.

Anche i file
Key Map
, che noi chiamiamo
File Tasti
, sono dei file in formato INI, la cui importanza specifica sarà chiarita più avanti. Fin qui ci eravamo limitati a dire che essi hanno l’estensione
JKM
, e che al loro interno erano registrati gli abbinamenti tra gli script ed i tasti che li attivano.

Ora, che conosciamo nel dettaglio il formato dei
File INI
, è giunto il momento di analizzarne uno in particolare, per capire come si realizza questa correlazione.

A tale scopo, seguite questi passi:

  1. Agite sul solito comando di apertura dei file dell’Utente,
    Control+O.
  2. Appena entrati nella finestra di dialogo, premete Tab una volta per portarvi nell’elenco dei tipi di file, scendete con la freccia fino a selezionare
    File Keymap (*.jkm)
    , quindi premete tre volte Shift+Tab per tornare alla casella di elenco.
  3. Premete la lettera
    D
    , e dovrebbe selezionarsi il file
    Default.JKM
    , quindi premete Invio.
  4. Poiché questo file potrebbe contenere numerose sezioni, come ad esempio quelle per l’uso con la barra Braille, portatevi su quella denominata
    Common Keys
    , (TastiComuni), dove sono poste una buona parte delle assegnazioni tasti che riguardano i nostri script. Cercate tale termine tramite il comando di ricerca testo, avendo l’accortezza di inserirlo in una coppia di parentesi quadre, come nella forma seguente:
  5. 
    [Common Keys]
    

In ogni caso, una volta giunti sull’etichetta della sezione, dalla riga sottostante iniziano le correlazioni tra tasti e script.

In ciascuna di esse, prima del carattere Uguale si trova il nome del tasto, o della combinazione tasti, che attiva lo script, la quale funge pertanto come chiave del dato.

Dopo il segno di Uguale, invece, si trova il nome dello script, che quindi in questo caso rappresenta il dato memorizzato.

Oltre a questa già analizzata, un’altra parte degli script di nostro interesse potrebbe essere elencata anche nelle sezioni
Desktop Keys
, (TastiDesktop), oppure
Laptop Keys
, (TastiLaptop). Quest’ultimo caso citato si proporrà solo quando, tra le impostazioni di Base di Jaws, alla voce
Usa Layout tastiera
, anziché la scelta standard
Desktop
, avessimo appunto scelto la voce
Laptop.

Chiudete ora il file aperto, con
Control+F4
, e passiamo ad un altro aspetto dell’argomento.

Il nostro file di configurazione.

Abbiamo già detto che sarà nostra cura servirci, ogni qualvolta sarà possibile, degli stessi file di configurazione utilizzati da Jaws per registrare dati relativi alle singole applicazioni. Nonostante ciò, allo stesso modo in cui abbiamo creato i nostri file personalizzati delle costanti, delle variabili globali e dei Messaggi, a maggior ragione dovremo crearci anche un nostro file di configurazione, dove scrivere tutte le informazioni di carattere generale che riguardano i nostri script, e che non siano quindi legate ai singoli programmi applicativi. Così facendo, oltre a centralizzare le informazioni specifiche di nostro interesse, questo archivio di configurazione Personale ci consentirà di esportare più facilmente i nostri script in eventuali nuove versioni di Jaws.

A questo nostro file di configurazione daremo il nome di
_PsDefault.JCF
, aggiungendo il solito prefisso
_Ps
al nome usato per il file di configurazione di Jaws. In particolare, nel sistema che andremo ad approntare, questo file ci servirà per informare Jaws su quali tipi di finestre debbano essere monitorate, e a quale livello i dati siano da rilevare.

Trattare i file INI.

Jaws ha molte funzioni che si occupano di scrivere e leggere i dati sui file di formato INI. In questo capitolo noi ne affronteremo alcune, delle quali le principali sono quattro:

  1. IniWriteInteger
    , (ScriviValoreNumericoFileIni).
  2. IniReadInteger
    , (LeggiValoreNumericoFileIni).
  3. IniWriteString
    , (ScriviDatoTestualeFileIni).
  4. IniReadString
    , (LeggiDatoTestualeFileIni).

Tutte e quattro hanno altrettanti parametri obbligatori.

  1. La
    Sezione
    del file INI da trattare.
  2. La
    chiave
    del dato da elaborare.
  3. Il
    dato
    da scrivere, nel caso delle due funzioni di scrittura, oppure un valore da restituire qualora il dato sia vuoto, nelle due funzioni di lettura.
  4. Il nome del
    File Configurazione
    su cui scrivere o leggere, espresso anche senza il percorso completo.

Le due funzioni di scrittura,
IniWriteInteger
e
IniWriteString
, avrebbero anche un quinto parametro opzionale. Questo parametro, se valorizzato con
TRUE
, oppure 1, attiva la scrittura su disco immediata, ed è l’opzione predefinita. Invece, col valore
FALSE
, oppure 0, tale svuotamento del buffer di memoria avverrà in un secondo momento. Per questo, di solito come quinto parametro non si specifica nulla, lasciando quindi l’impostazione predefinita.

A ciascuno di questi comandi appena citati saranno dedicate altrettante nostre funzioni, tramite le quali avremo il vantaggio di poter preimpostare i parametri che risulteranno dei dati fissi, dovendo perciò poi specificare solo quelli variabili.

Scrivere e leggere il livello della finestra.

La prima coppia di funzioni integrate, fra quelle citate in precedenza, si occuperà appunto di registrare nel file di configurazione, e poi da questo rilevare, il valore numerico corrispondente al livello delle finestre a cui leggere i dati a noi necessari.

Se ricordate, i livelli delle finestre che avevamo definito sono tre, ed altrettante le costanti che li rappresentano:

  1. CORRENTE, di valore 1.
  2. REALE, di valore 2.
  3. PRINCIPALE, di valore 3.

Trattandosi di un valore numerico, quindi di un dato di tipo
Integer
, le due funzioni integrate saranno:

  1. IniWriteInteger ()
    , per scriverlo.
  2. IniReadInteger ()
    , per leggerlo.

Le nostre funzioni, che conterranno tali istruzioni di Jaws, saranno tra breve illustrate ciascuna nel dettaglio, spiegando anche le differenze di struttura fra l’una e l’altra.

Queste funzioni da noi realizzate, a loro volta, ricaveranno il nome dell’archivio dei dati da trattare, che equivale al loro quarto parametro, tramite un’altra funzione da noi prodotta. Per quanto già detto, circa il fatto di realizzare prima le funzioni che sono chiamate successivamente da altre funzioni o script, il nostro primo codice scritto sarà perciò proprio quello illustrato di seguito.

Esercizio 7.2.6. La funzione NomeArchivio.

FileScript.

Default.JSS

Nome.

NomeArchivio

Descrizione.

Imposta il nome del file archivio da elaborare, sulla base del valore specificato come parametro, restituendolo con l’aggiunta dell’opportuna estensione.

Ritorni.

Di tipo String. Il nome dell’archivio completo di estensione.

Parametri.
  1. iTipo. Il valore numerico corrispondente all’archivio da impostare. Di tipo Int.
Novità.
  1. La funzione
    GetActiveConfiguration ()
    , già illustrata i precedenza, senza parametri.
  2. Le costanti
    Personale
    e e
    PS_FILE
    , relative alle nostre impostazioni, la prima con valore 2 e che identifica il tipo di archivio da restituire, la seconda che contiene il nome base degli archivi personali.
  3. L’altra costante
    JCF
    , che corrisponde all’estensione per gli archivi di Configurazione.
Note.
  1. Questa struttura di controllo è stata inserita in una funzione per avere la possibilità di unificare, per tutti gli script, il nome e la forma dei file di configurazione. In altre parole, qualora si dovesse per qualche motivo cambiare, ad esempio aggiungendo un percorso per tale tipo di archivio, la modifica andrebbe eseguita soltanto qui, e non in tutti i riferimenti esistenti, in questo file script Predefinito o negli altri per le applicazioni locali. Inoltre, tale struttura potrà poi restituire anche altri tipi di archivio, aggiungendo il controllo relativo ad un altro valore e l’istruzione che restituisce l’ulteriore tipo di nome.
  2. Oltre a quella citata tra le Novità, qui sarà usata un’altra costante,
    CORRENTE
    , che se ricordate abbiamo impostato ed utilizzato fin dal capitolo 5. Questo rappresenta un esempio di come si possano comunque sfruttare dati utilizzati in script precedenti, purché si cerchi di dar loro dei nomi il più possibile standard, e che possano quindi assumere diversi significati.

Codice.


String Function NomeArchivio (int iTipo)
; compone il nome dell’archivio da restituire aggiungendo l’estensione necessaria
If iTipo == CORRENTE Then; Per l’archivio di Configurazione dell’applicazione attiva,
Return GetActiveConfiguration () + JCF; usa la funzione originale
ElIf iTipo == PERSONALE Then; per l’archivio delle Impostazioni personali,
Return PS_FILE + JCF; utilizza l’apposita costante
EndIf; fine controllo tipo archivio
EndFunction

Collaudo.

Come al solito, per questa e le funzioni che seguiranno, ci si potrà limitare a salvare compilando, mentre il test sul lavoro svolto sarà effettuato al primo script utile.

Esercizio 7.2.7. La funzione ScriveLivelloFinestra.

FileScript.

Default.JSS

Nome.

ScriveLivelloFinestra

Descrizione.

scrive nel file di configurazione Personale il livello della finestra di cui rilevare i dati.

Ritorni.

Di tipo Int. L’esito della scrittura: TRUE, in caso di riuscita; FALSE, per un risultato nullo.

Parametri.
  1. sNomeTipo. Il nome assegnato alla tipologia di finestre di cui rilevare i dati. Di tipo String.
  2. iLivello. Il valore numerico che identifica il livello, corrispondente ai tre possibili:
    CORRENTE,
    REALE
    e
    PRINCIPALE
    . Di tipo Int.
Novità.
  1. La funzione di scrittura
    IniWriteInteger ().
  2. La costante
    TIPI_FINESTRE
    , che rappresenta il nome della sezione nel file archivio cui scrivere il valore numerico.
  3. L’utilizzo della nostra funzione
    NomeArchivio ()
    , usando come parametro la costante
    PERSONALE.
Fasi.
  1. Tenta di scrivere il valore del livello di finestra, tramite la citata funzione di scrittura, che per i suoi quattro parametri ne utilizza due di preimpostati e due provenienti dai parametri specificati al momento di chiamare la nostra funzione.
  2. L’esito della funzione di scrittura viene inserito in una struttura di controllo che, sia in caso di riuscita, sia in quello di fallimento, fa leggere un messaggio e ne restituisce i valore,
    TRUE
    o
    FALSE
    , rispettivamente.
Note.

Come già in parte anticipato, i vantaggi di aver inserito l’istruzione di scrittura in una nostra funzione, anziché utilizzarla direttamente nel codice, sono molteplici:

  1. Ci consente di omettere due parametri su quattro ad ogni chiamata della funzione, poiché gli altri due sono già preimpostati nella funzione stessa.
  2. Per quanto detto al punto precedente, e grazie al nome esplicativo dato alla funzione, si rende il codice più facilmente leggibile e snello.
  3. L’esito della funzione viene pronunciato direttamente da Jaws, senza altre nostre strutture di controllo , e lo fa in modo modo versatile, sulla base dei livelli di prolissità da noi utilizzati.

Codice.


String Function ScriveLivelloFinestra (string sNomeTipo, int iLivello)
If IniWriteInteger ( ; Tenta di scrivere il valore nella configurazione Personale
TIPI_FINESTRE, ; parametro1, sezione del file, dato fisso
sNomeTipo, ; parametro2, il tipo di finestra che funge da chiave
iLivello, ; parametro3, il valore numerico con il livello di finestra
NomeArchivio (PERSONALE)); parametro4, il file configurazione Personale, dato fisso
Then; se la scrittura riesce, prima legge l’avviso,
SayFormattedMessage (OT_ERROR, hlpScritturaOk, hlpScritturaOk_corto, sNomeTipo)
Return TRUE; poi restituisce l’esito positivo
Else; altrimenti, prima avvisa dell’errore,
SayFormattedMessage (OT_ERROR, hlpNoScrittura, hlpNoScrittura_corto, sNomeTipo)
Return FALSE; poi restituisce un risultato nullo
EndIf; fine controllo esito
EndFunction

Esercizio 7.2.8. La funzione LeggeLivelloFinestra.

FileScript.

Default.JSS

Nome.

LeggeLivelloFinestra

Descrizione.

Legge il valore del livello di finestra registrato nell’archivio Personale come dato della tipologia di finestra, quest’ultima indicata come unico parametro della funzione.

Ritorni.

Di tipo Int. Il valore del livello di finestra a cui rilevare i dati.

Parametri.
  1. sNomeTipo. Il nome assegnato alla tipologia di finestre di cui rilevare i dati. Di tipo String.
Novità.
  1. La funzione di lettura
    IniReadInteger ().
Note.
  1. Il nostro elemento di codice contiene la sola chiamata alla funzione di lettura appena citata, che è inserita nella nostra funzione per consentirci sia di risparmiare tre parametri su quattro, che sono preimpostati nella funzione stessa, sia per rendere più leggibile e snello il codice.
  2. Da far notare, come terzo parametro di
    IniReadInteger ()
    , l’uso del valore
    FALSE
    , come dato predefinito da restituire nel caso in cui la funzione non riuscisse a leggere alcun dato dal file configurazione.
  3. Diversamente dalla precedente, in questa funzione il nome dell’archivio Personale non viene memorizzato in una variabile locale perché esso viene usato una volta sola.

Codice.


Int Function LeggeLivelloFinestra (string sNomeTipo)
Return IniReadInteger ( ; restituisce il valore memorizzato nel file configurazione Personale
TIPI_FINESTRE, ; parametro1, sezione del file, dato fisso
sNomeTipo, ; parametro2, il tipo di finestra che funge da chiave
FALSE, ; parametro3, il valore restituito in caso di mancata lettura, dato fisso
NomeArchivio (PERSONALE)) ; parametro4, file di configurazione Personale
EndFunction

Scrivere e leggere il codice identificativo di una finestra.

L’altra coppia di funzioni, che andremo ora a realizzare, si occupa di trattare un dato testuale. Per questo, coinvolgerà le altre due funzioni rimaste, delle quattro illustrate all’inizio:

  1. IniWriteString ()
    , per scriverlo.
  2. IniReadString ()
    , per leggerlo.

Il dato da trattare sarà il codice identificativo personale delle finestre che, se ricordate, può assumere due formati diversi, con due o tre dati sulle finestre separati da trattini.

a Parte questa differenza, le funzioni da realizzare sono per il resto pressoché identiche alle prime due, ed anche per questo forniremo molte meno informazioni per crearle. Tra l’altro, avremo modo qua e là di trovare anche dei riferimenti a quanto fatto nel capitolo precedente, sfruttando così il lavoro già svolto. E proprio il dato testuale da trattare ne sarà un primo esempio, essendo ricavato dalla nostra apposita funzione, realizzata nel capitolo precedente,
CodiceFinestra ()
, che crea appunto il codice personale per identificare in quale finestra ci si trovi.

Esercizio 7.2.10. La funzione ScriveCodiceFinestra.

FileScript.

Default.JSS

Nome.

ScriveCodiceFinestra

Descrizione.

scrive nel file di configurazione dell’applicazione attiva il codice identificativo personale della finestra di cui rilevare i dati.

Ritorni.

Di tipo Int. L’esito della scrittura: TRUE, in caso di riuscita; FALSE, per un risultato nullo.

Parametri.
  1. sNomeTipo. Il nome assegnato alla tipologia di finestre di cui rilevare i dati. Di tipo String.
  2. sCodice. La stringa che rappresenta il codice identificativo personale della finestra di cui leggere i dati. Di tipo String.
Novità.
  1. La funzione di scrittura
    IniWriteString ().
  2. La costante
    DATI_FINESTRE
    , che rappresenta il nome della sezione nel file archivio dell’applicazione corrente cui scrivere il codice identificativo.
Fasi.
  1. Tenta di scrivere il codice identificativo della finestra tramite la citata funzione di scrittura, che per i suoi quattro parametri ne utilizza due di preimpostati e due provenienti dai parametri specificati al momento di chiamare la nostra funzione.
  2. L’esito della funzione di scrittura viene inserito in una struttura di controllo che, sia in caso di riuscita, sia in quello di fallimento, fa leggere il relativo messaggio, e ne restituisce poi un valore,
    TRUE
    o
    FALSE
    , rispettivamente.

Codice.


Int Function ScriveCodiceFinestra (string sNomeTipo, string sCodice)
If IniWriteString ( ; Tenta di scrivere il dato nel file dell’applicazione corrente
DATI_FINESTRE, ; parametro1, sezione del file, dato fisso
sNomeTipo, ; parametro2, il tipo di finestra che funge da chiave
sCodice, ; parametro3, il dato testuale con il codice della finestra
NomeArchivio (CORRENTE)); parametro4, file configurazione dell’applicativo corrente
Then; se la scrittura riesce, prima legge l’avviso,
SayFormattedMessage (OT_ERROR, hlpScritturaOk, hlpScritturaOk_corto, sNomeTipo)
Return TRUE; poi restituisce l’esito positivo
Else; altrimenti, prima avvisa dell’errore,
SayFormattedMessage (OT_ERROR, hlpNoScrittura, hlpNoScrittura_corto, sNomeTipo)
Return FALSE; poi restituisce un risultato nullo
EndIf; fine controllo esito
EndFunction

Esercizio 7.2.11. La funzione LeggeCodiceFinestra.

FileScript.

Default.JSS

Nome.

LeggeCodiceFinestra

Descrizione.

Legge il codice identificativo della finestra registrato nell’archivio dell’applicativo corrente, avente come chiave la tipologia di finestra specificata come unico parametro della funzione.

Ritorni.

Di tipo String. Il codice identificativo della finestra del tipo specificato.

Parametri.
  1. sNomeTipo. Il nome assegnato alla tipologia di finestre di cui rilevare i dati. Di tipo String.
Novità.
  1. La funzione di lettura
    IniReadString ().
Note.

Da far notare, come terzo parametro della citata funzione di lettura, l’uso della costante
NULLO
, come stringa vuota da restituire nel caso in cui la funzione non riuscisse a leggere alcun dato dal file configurazione.

Codice.


String Function LeggeCodiceFinestra (string sNomeTipo)
Return IniReadString ( ; restituisce il dato memorizzato nel file per l’applicazione corrente
DATI_FINESTRE, ; parametro1, sezione del file, dato fisso
sNomeTipo, ; parametro2, il tipo di finestra che funge da chiave
NULLO, ; parametro3, la stringa vuota restituita in caso di mancata lettura, dato fisso
NomeArchivio (CORRENTE)); parametro4, file archivio dell’applicativo ottenuto dalla funzione
EndFunction

Lo script di Prova.

Quando si realizza una serie di funzioni, come nel nostro caso, può capitare di sentire l’esigenza di testare comunque il frutto del proprio lavoro, se non altro per capire se si sta procedendo per la strada giusta. In questi casi si può ricorrere ad uno script di prova, dove poter impostare, anche a mano, il minimo di dati necessari per poter collaudare le funzioni.

Vale quindi la pena, anche per farvi capire bene il nostro percorso, di provare a scriverne uno. Lo realizzeremo dentro al file script Predefinito, e da lì dovrà inoltre essere eseguito.

Quanto al suo contenuto, ci limiteremo a chiamare le due coppie di funzioni di scrittura e lettura appena realizzate. Al loro interno andranno specificati i parametri relativi alla tipologia di finestra da elaborare, quella che abbiamo salvato nella costante
EDITING
, ed i dati che sono relativi al livello
CORRENTE
della finestra.

Le due funzioni di scrittura, in quanto già contenenti le istruzioni che ne leggono l’esito, potranno essere delle chiamate a sé stanti. Quelle di lettura, in quanto si limitano a restituire un risultato, saranno invece inserite in due semplici comandi di questo tipo, di un dato numerico e testuale rispettivamente. Stavolta, a tale scopo, torniamo ad usare le vecchie istruzioni
SayInteger ()
e
SayString ()
, le quali hanno se non altro la particolarità di leggere i messaggi con il tono normale di Jaws, e così creando un’alternanza con quelli dal tono minore letti dalle due funzioni di scrittura.

i commenti nel codice dovrebbero essere sufficienti ad illustrarne l’azione, anche perché questo tipo di script dovrebbe essere un intermezzo veloce, cui non si dedichi particolare attenzione formale.

Esercizio 7.2.13. Lo script Prova.

FileScript.

Default.JSS

Nome.

Prova

Sommario.

Esegue dei test.

Descrizione.

Consente di eseguire alcune istruzioni che non sono attualmente chiamate in altri elementi di codice.

TastiAttivazione.

Alt+Control+Apostrofo

Codice.


Script Prova ()
; trascrive il livello della finestra nel file configurazione Personale, e ne legge l’esito
ScriveLivelloFinestra (EDITING, CORRENTE)
SayInteger (LeggeLivelloFinestra (EDITING)); legge il valore appena registrato
; Trascrive il codice identificativo nell’archivio dell’applicazione attiva, e ne legge l’esito
ScriveCodiceFinestra (EDITING, CodiceFinestra (CORRENTE));
SayString (LeggeCodiceFinestra (EDITING)); legge il codice appena registrato
EndScript

Collaudo.

Dopo il salvataggio, si raccomanda di rimanere nella finestra di editazione dell’Editor, e da qui premere la combinazione tasti che esegue lo script,
Alt+Control+Apostrofo.

Se tutto va bene, le righe pronunciate da Jaws dovrebbero avere un aspetto simile:


Dati salvati...
1
Dati salvati...
nn-nn-ttttt

Come spiegazione, i due messaggi estesi danno l’esito della scrittura, che potranno essere letti nella loro versione lunga, quella che contiene anche il nome dell’archivio, oppure nella versione corta, a seconda del livello di prolissità utilizzato.

Il valore 1 è invece quello letto dal file personale, che equivale al livello a cui leggere i dati della finestra, in questo caso quello corrente.

L’ultima stringa, infine, è il codice identificativo personale, con i dati della finestra di editazione dell’Editor di Script per il livello Corrente, formattati secondo il codice che avevamo stabilito.

Se volete ricontrollare il testo di ciò che Jaws ha pronunciato, consultate la
Cronologia della Sintesi
, che si attiva premendo
TastoJaws+BarraSpazio, lettera H.

La cosa importante da evidenziare è che, oltre a fare un test sulle funzioni create, noi con questo breve script abbiamo già impostato i valori necessari al funzionamento della nostra procedura con la finestra che abbiamo chiamato
Editing.

Andiamo però a controllare direttamente cosa abbiamo fatto, aprendo i file configurazione che dovremmo aver creato. Provate quindi a seguire questi passi:

  1. Aprite la cartella dei file Utente, e nella casella
    Tipo di file
    , scendete sino all’ultima voce,
    Tutti i file (*.*).
  2. Tornate nella casella elenco con la lista dei file, dove selezionare e quindi aprire il file
    _PsDefault.JCF
    , che potrete raggiungere premendo due volte il carattere Sottolineato.
  3. Una volta dentro al file, il suo contenuto dovrebbe essere il seguente:
  4. 
    [TipiFinestre]
    Editing=1
    

Secondo lo schema che abbiamo già visto in precedenza, nell’ordine:

  1. Il contenuto della costante
    TIPI_FINESTRE
    è diventata l’etichetta con il nome della sezione in cui sono contenuti i dati.
  2. Il contenuto della costante
    EDITING
    è stata trascritta nell’omonima chiave del dato.
  3. Il valore 1, quello scelto come livello a cui leggere la finestra, è il dato numerico inserito, che corrisponde al contenuto della costante
    CORRENTE.

Ora, per completare il controllo, ripetete questa procedura per aprire il file di configurazione dell’Editor di Script.

Qui dovrete cercare un file che potrebbe chiamarsi o
editor di script.JCF
, oppure
script manager.JCF
, quest’ultima versione per Jaws 18 o per quelle in inglese.

In ogni caso, una volta aperto, il suo contenuto dovrebbe avere questo aspetto:


[DatiFinestre]
Editing=nn-nn-ttttt

Anche qui, dunque, lo stesso schema, con la Sezione,
DatiFinestre
, la Chiave,
Editing
, ed il Dato, con i valori da voi rilevati.

Va detto subito che questa prima registrazione, indispensabile affinché il sistema funzioni, dalla prossima volta potrà essere eseguita anche dalla procedura stessa, seppure chiedendoci conferma. In pratica, quello che abbiamo fatto dapprima realizzando, e poi eseguendo, lo script di prova, lo potremo ripetere con ciascuno script e ciascuna finestra, direttamente dall’applicazione su cui stiamo operando, semplicemente con qualche pressione di tasti di selezione o conferma.

Abbiate la pazienza di completare il sistema, poi il suo utilizzo renderà tutto più semplice.

***

Impostare i dati per le finestre.

Le quattro nostre funzioni di scrittura e lettura sono in pratica il
"motore"
del sistema, quelle che fanno materialmente qualcosa. Le restanti funzioni da realizzare si possono definire di
Gestione
, in quanto eseguono controlli preventivi, o compiono azioni conseguenti, all’operato delle prime. A loro volta, le funzioni di Gestione saranno chiamate da altre funzioni o da script, con l’unico scopo di frammentare il più possibile il codice al fine di renderlo maggiormente comprensibile.

Da qui alla fine del capitolo realizzeremo tutte funzioni di questo tipo, più lo script vero e proprio, che anch’esso è in sostanza un gestore di azioni diverse.

In pratica, noi stiamo creando un sistema che, a regime, riuscirà a guidarci ad una registrazione dei dati relativi alle finestre, se non proprio automatica, almeno molto interattiva. Ci sono tuttavia dei livelli per i quali sarà necessario comunque agire noi direttamente, sia lanciando uno script che ne gestisce le impostazioni, sia dovendo inserire alcune assegnazioni particolari nel nostro file delle costanti.

Parlando in particolare dello script, esso si chiamerà
DefinisceTipiFinestra
. Il suo compito sarà, appunto, definire quale nome assegnare ad un determinato tipo di finestra, e casomai scegliere a quale livello leggere i suoi dati.

Si tratta di quello che noi, nello scorso capitolo, abbiamo fatto decidendo che la finestra che volevamo monitorare si sarebbe chiamata
Editing
, e sarebbe stata letta a livello
CORRENTE
, cui abbiamo fissato un valore 1. Entro la fine del capitolo, quando faremo il collaudo del nostro sistema, lo useremo per determinare dei nuovi tipi di finestra nell’Editor di Script.

Volendo rispettare la gerarchia di cui si parlava, e quindi realizzando per primi gli elementi di codice che saranno chiamati dagli altri, il nostro script chiamerà le altre funzioni in quest’ordine:

  1. Una nostra funzione,
    LeggeChiavi
    , che rileverà l’elenco dei dati inseriti nel file di configurazione specificato come parametro.
  2. La funzione integrata
    DlgSelectItemInList ()
    , che servirà a scegliere quale dei tipi rilevati sarà scelto , oppure se aggiungerne uno nuovo.
  3. Nel caso in cui se ne debba definire uno di nuovo, la nostra funzione
    NuovoTipoFinestra
    , che consentirà sia di impostarne un nome inedito, sia di assegnare ad esso un livello di finestra.
  4. Le funzioni integrate
    StringSegmentCount ()
    e
    StringSegment ()
    , che ci consentiranno casomai di estrarre dall’elenco la voce testuale relativa al tipo scelto.
  5. La nostra funzione
    ControllaScritturaCodice
    , che consente di confermare o meno la registrazione del codice identificativo personale della finestra.

Come potete notare, tre nostre funzioni, alla quale si aggiungono:

  1. Una quarta,
    DefinisceLivello
    , a sua volta chiamata da
    NuovoTipoFinestra
    , la quale si occupa di gestire la scelta e successiva registrazione del livello a cui leggere la finestra;
  2. Una quinta,
    CancellaChiave
    , stavolta chiamata da
    ControllaScritturaCodice
    , che serve soltanto a cancellare un dato con la sua chiave.

Dopo questa breve panoramica, tanto per capire su cosa stiamo operando, dobbiamo ora aprire due parentesi, in cui parlare nel dettaglio di altrettante funzioni speciali di Jaws.

La Funzione Integrata ExMessageBox.

Dopo aver trattato ed utilizzato già più volte
DlgSelectItemInList ()
, presenteremo ora altre due fondamentali funzioni integrate che ci consentono di realizzare degli script interattivi usando Jaws.

La prima di queste è
ExMessageBox
, (CasellaMessaggi), la quale presenta a video una finestra di dialogo nel classico stile Windows. Tale finestra offre diverse possibilità di mostrare conferme e pulsanti di scelta, in differenti modalità da configurare a piacimento.

La funzione ha soli tre parametri:

  1. Il testo del messaggio visualizzato, che appare a video in una casella di sola lettura.
  2. Il titolo della finestra di dialogo, che si può rileggere assieme al titolo dell’applicazione.
  3. Il tipo di controllo da mostrare, configurabile con varie icone e segnali acustici.

Dei primi due non c’è molto da dire, se non che sono due dati testuali, da utilizzare casomai con delle assegnazioni di messaggi. Del terzo parametro, invece, ci sarebbero diverse informazioni da fornire, ma ci limiteremo ora all’essenziale.

Intanto, il parametro è costituito da una serie di valori, memorizzati in costanti che, nel file costanti Predefinito
HJConst.JSH
, sono riconoscibili per avere tutte il prefisso
MB_
, acronimo che sta appunto per
Message Box
. Di queste costanti se ne possono inserire più d’una, separandole una dall’altra con il carattere
PIPE,
|
, purché appartengano ciascuna ad una delle diverse tipologie di costanti:

  1. Il tipo di controllo.
  2. Il tipo di icona e di segnale acustico collegato.
  3. Il posizionamento dei controlli.
  4. Il pulsante predefinito, che si attiva premendo Invio.

Di queste, la più importante è la prima, quella che determina il tipo di controllo proposto. In questo caso, i tipi possibili di controlli sono i seguenti:

  1. MB_OK
    , che propone il solo pulsante
    "Ok".
  2. MB_OKCANCEL
    , che mostra sia
    "Ok"
    che
    "Annulla".
  3. MB_ABORTRETRYIGNORE
    , che propone la scelta tra
    "Interrompi",
    "Riprova"
    e
    "Ignora".
  4. MB_YESNOCANCEL
    , che mostra i pulsanti
    "Sì",
    "No"
    e Annulla.
  5. MB_YESNO
    , che mostra solo
    "Sì"
    o
    "No".
  6. MB_RETRYCANCEL
    , che propone
    "Riprova"
    o
    "Annulla".

Noi, in questo capitolo, ci limiteremo ad utilizzare le opzioni 4 e 5.

All’interno degli script, per sapere quale tasto ha premuto l’utente, a ciascuno dei diversi pulsanti proposti corrisponde un valore differente, che viene restituito dalla funzione e che può quindi essere memorizzato in una variabile di tipo numerico. Tale valore può essere registrato direttamente, usando la forma seguente:


Let iValore = ExMessageBox (sMessaggio, sTitolo, sTipoControllo)

Gli abbinamenti tra valori restituiti e tasti premuti, con questi ultimi che hanno il nome preceduto dal prefisso
ID
, sono anch’essi registrati nel file
HJConst.JSH
. Di questi , i principali sono elencati di seguito, con la traduzione nel commento:


IDOK = 1, ; Ok
IDCANCEL = 2, ; Annulla
IDABORT = 3, ; Interrompi
IDRETRY = 4, ; Riprova
IDIGNORE = 5, ; Ignora
IDYES = 6, ; Sì
IDNO = 7, No

Come sempre, il primo esempio di utilizzo di
ExMessageBox ()
, che faremo nella prossima funzione, potrà fare maggiore chiarezza.

La funzione integrata InputBox.

Per Poter registrare del testo in una variabile, inserendola dalla tastiera, Jaws fornisce la funzione
InputBox
, (CasellaInserimento), dove si può specificare del testo in un normale campo di editazione in stile Windows, con un tasto
Ok
ed un tasto
Annulla.

La funzione ha tre parametri:

  1. Un messaggio che si vuole sia visualizzato come prompt della casella di editazione.
  2. Il titolo della finestra di dialogo, che si potrà rileggere con
    TastoJaws+T.
  3. Il nome di una variabile di tipo String, cui sarà assegnato il testo digitato nella casella.

Una volta entrati nello spazio editabile, il testo potrà essere scritto nella riga corrente, confermandolo poi con
Ok
oppure Invio. Sarà inoltre possibile digitarlo su più righe, purché a fine di ciascuna riga, per crearne una di nuova, si prema il tasto
Control
assieme ad Invio.

Al termine, premendo solo Invio, oppure il pulsante
Ok
, si concluderà l’inserimento e si uscirà dalla finestra di dialogo.

La fase di scrittura si interromperà anche premendo il tasto Escape, o confermando il pulsante
Annulla
. In questo caso, però, sarà assegnata alla variabile una stringa vuota, a prescindere dal testo eventualmente inserito.

Da notare che, in caso di immissione su più righe, la stringa registrata avrà come caratteri di fine riga una coppia di Ascii 13 e 10, aspetto che vedremo più avanti avere un qualche rilievo.

Oltre alla variabile testuale, la funzione restituirà anche un valore numerico, che avrà solo due alternative:

  • 1, oppure TRUE, se si termina con Invio.
  • 0, o FALSE, se si finisce con Escape.

Tale valore dovrà essere assegnato come risultato della funzione, secondo lo schema seguente:


Let iValore = InputBox (sMessaggio, sTitolo, sVariabile)

Un’ultima annotazione: la variabile testuale indicata come terzo parametro sarà
per riferimento
, concetto cui abbiamo già accennato ed a cui dedicheremo il prossimo argomento. Nel frattempo, basterà dire che, se la variabile da noi specificata avesse già un proprio contenuto, questo sarebbe inserito automaticamente nel campo di editazione all’ingresso nella finestra di dialogo. Questo contenuto, ovviamente, potrà poi essere modificato o eliminato in fase di editazione, ma alla fine assumerà il testo che risulterà impostato al momento dell’uscita tramite Invio.

Ancora una cosa, su questo: qualora si avesse del testo già presente nella variabile prima della chiamata della funzione
InputBox ()
, e tale contenuto fosse quindi come detto proposto a video all’ingresso della schermata di dialogo, premendo Escape si uscirebbe dalla funzione cancellando però anche il precedente contenuto della variabile.

Le variabili per riferimento.

A volte c’è bisogno che una funzione ci restituisca non uno solo, bensì due, tre o anche più risultati. In questi casi, il modo più semplice è quello di far sì che alcune variabili, poste come parametri della funzione), siano
trasmesse
all’elemento di codice che l’ha chiamata, impostandone un valore all’interno della funzione stessa.

Normalmente, quando si chiama una funzione, un valore passato come parametro va solo in una direzione, dall’elemento di codice chiamante alla funzione chiamata. Con le variabili
per riferimento
, invece, le informazioni si muovono avanti ed indietro, nelle due direzioni, restituendo, tramite la variabile posta come parametro, o il valore originale, oppure quello eventualmente modificato dalla funzione chiamata.

Nel codice, ciò che distingue un parametro dall’essere di tipo normale, oppure per riferimento, è l’abbreviazione
ByRef
, che sta per la traduzione letterale in inglese
ByReference
. Tale abbreviazione è posta tra la dichiarazione del tipo di variabile ed il suo nome, sempre all’interno delle parentesi dopo il nome dell’elemento di codice.

Oltre a servirsene con la funzione
InputBox ()
, che abbiamo appena presentato, ritroveremo questo tipo particolare di parametro in alcuni dei prossimi esercizi da qui alla fine del capitolo. Sarà quindi più semplice capire come funzionano, analizzandone il modo concreto di lavorare al nostro servizio.

Ora, dopo questa ampia ma necessaria parentesi teorica, riprendiamo finalmente a scrivere del codice.

Esercizio 7.3.4. La funzione LeggeChiavi.

FileScript.

Default.JSS

Nome.

LeggeChiavi

Descrizione.

Rileva tutti i dati eventualmente registrati nella sezione specificata, nel file di configurazione del tipo indicato, casomai inserendoli in un elenco con ciascuna voce separata tramite un carattere PIPE.

Ritorni.

Di tipo String. L’elenco dei dati rilevati nel file di configurazione.

Parametri.
  1. iTipo. Il valore numerico corrispondente all’archivio da impostare. Di tipo Int.
  2. sSezione. L’etichetta della sezione di cui leggere i dati nell’archivio. Di tipo String.
Novità.
  1. La funzione integrata
    IniReadSectionKeys
    , (LeggiChiaviDiSezioneNeiFileIni), che serve a rilevare l’elenco dei dati già registrati in una determinata sezione di un archivio. Ha due parametri:
    • La sezione in cui cercare i dati.
    • Il nome dell’archivio da cui leggerli.
Note.

La funzione serve a chiamare quella integrata
IniReadSectionKeys ()
, guadagnando in leggibilità e semplificando il modo di individuare il nome dell’archivio.

Codice.


String Function LeggeChiavi (int iTipo, string sSezione)
Return IniReadSectionKeys ( ; legge i dati specificati dall’archivio impostato
sSezione, ; parametro1, nome della sezione da cui leggere i dati
NomeArchivio (iTipo)); parametro2, nome dell’archivio del tipo specificato
EndFunction

Esercizio 7.3.5. La funzione DefinisceLivello.

FileScript.

Default.JSS

Nome.

DefinisceLivello

Descrizione.

Consente di scegliere un livello a cui leggere la finestra, inserendo una conferma all’eventuale uscita dalla finestra di dialogo senza scegliere alcun valore. Nel caso fosse operata una scelta, restituisce l’esito della scrittura dei dati sul file configurazione Personale.

Ritorni.

Di tipo Int. L’esito dell’impostazione: TRUE, in caso di riuscita; FALSE, per un risultato nullo.

Parametri.
  1. sNomeTipo
    . Il nome del tipo di finestra di cui leggere i dati. Di tipo String.
  2. iLivello. Per Riferimento. Il livello a cui leggere i dati della finestra. Di tipo Int.
Novità.
  1. La funzione integrata
    ExMessageBox ()
    , in cui le costanti native
    MB_YESNO
    e
    MB_ICONQUESTION
    , assegnano quale debbano essere, nell’ordine, prima la finestra di dialogo, poi il segnale acustico e l’icona a video.
  2. Le costanti native
    IDYES
    e
    IDNO
    , che corrispondono al valore delle risposte sì e no alla finestra di dialogo.
  3. Il primo utilizzo di una variabile
    per riferimento
    , argomento cui anche in questo caso abbiamo dedicato un titolo a parte.
Fasi.
  1. Un ciclo
    While
    , che consente di ripetere l’inserimento finché una scelta sia operata.
  2. La chiamata della nostra funzione
    SceltaLivello ()
    , con la quale scegliere materialmente il valore.
  3. L’eventuale richiesta di conferma all’uscita, nel caso in cui non fosse stata operata nessuna scelta.
  4. All’uscita dal ciclo, in caso di valore impostato, la chiamata della nostra funzione
    ScriveLivelloFinestra ()
    , con la quale si può trascrivere tale valore nell’archivio di configurazione Personale.
Note.

Se si opera una scelta, il ciclo termina immediatamente restituendo il valore confermato. Se invece non si seleziona alcun livello di finestra, la richiesta di conferma consente di poter operare una eventuale nuova scelta, qualora si sia interrotta l’azione per errore.

Codice.


Int Function DefinisceLivello (string sNomeTipo, int ByRef iLivello)
Var Int iScelta; un valore da impostare
; trasmette con una variabile globale il nome del tipo di finestra di cui scegliere il livello
Let gsNomeFinestra = sNomeTipo
While !iScelta; esegue un ciclo, proponendo la richiesta finché la scelta rimane a zero
Let iScelta = SceltaLivello (); determina il livello cui leggere i dati della finestra
If !iScelta Then; se non è stata effettuata nessuna scelta,
Let iScelta = ExMessageBox (; propone una conferma all’uscita
msgConfermaUscita, ; parametro1, messaggio per il corpo della finestra di dialogo
ttlConfermaUscita, ; titolo della finestra di conferma
MB_YESNO|MB_ICONQUESTION); parametro3, tipo di controllo e dell’icona
If iScelta == IDNO Then; se è stato scelto No,
Let iScelta = FALSE; azzera il valore per consentire un ritorno all’inizio del ciclo
EndIf; fine controllo conferma
EndIf; fine controllo scelta effettuata
EndWhile; fine del ciclo di scelta
If iScelta == IDYES Then; se si è confermata l’uscita dalla procedura,
Return FALSE; restituisce un risultato nullo
ElIf ScriveLivelloFinestra (sNomeTipo, iScelta) Then; se la scrittura dei dati riesce,
Let iLivello = iScelta; trasmette la scelta effettuata
Return TRUE; restituisce l’esito positivo
Else; altrimenti,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo ritorno
EndFunction

Esercizio 7.3.6. La funzione NuovoTipoFinestra.

FileScript.

Default.JSS

Nome.

NuovoTipoFinestra

Descrizione.

Consente di specificare un nuovo tipo di finestra da monitorare, compreso il livello a cui leggervi i dati.

Ritorni.

Di tipo Void. Nessuno.

Parametri.
  1. sNomeTipo. Per Riferimento. Il nome del tipo di finestra di cui leggere i dati. Di tipo String.
  2. iLivello. Per Riferimento. Il livello della finestra a cui leggere i dati. Di tipo Int.
Novità.
  1. La funzione integrata
    InputBox ()
    , cui abbiamo dedicato un titolo apposito, che serve in questo caso ad indicare il nome per il nuovo tipo di finestra da monitorare.
  2. La chiamata della nostra funzione
    DefinisceLivello ()
    , per gestire la scelta del livello di finestra di cui leggere i dati.
Fasi.
  1. Tramite
    InputBox ()
    , si specifica il nuovo nome da assegnare al tipo di finestra. Nel caso in cui la procedura abbia avvisato della necessità di impostare uno dei tipi di finestra già previsti nel codice, all’ingresso nel campo d’inserimento tale nome sarà già scritto, in quanto memorizzato nella variabile globale
    gsNomeFinestra
    , potendolo così anche solo confermare con Invio.
  2. In una struttura annidata con tre controlli, si verifica dapprima la presenza del nuovo nome.
  3. In caso affermativo, si consente di abbinare un livello di finestra a tale nome, tramite la nostra funzione
    DefinisceLivello ().
  4. Se un livello è stato specificato, e se la registrazione dei dati va a buon fine, si restituisce un esito positivo, altrimenti si cancella anche il tipo già impostato.
  5. Se uno qualsiasi dei precedenti controlli fosse fallito, viene restituito un risultato nullo.

Codice.


Void Function NuovoTipoFinestra (string ByRef sNomeTipo, int ByRef iLivello)
Var Int iTasto; il valore del tasto premuto
Let sNomeTipo = gsNomeFinestra; si premette il nome casomai segnalato dalla procedura
Let iTasto = InputBox ( ; Consente di specificare un nuovo tipo di finestra
msgInserisciRiga, ; parametro1, l’avviso per il prompt della casella di editazione
ttlTipoNuovoFinestra, ; parametro2, titolo della finestra di dialogo
sNomeTipo); parametro3, il nome da impostare, per riferimento
If sNomeTipo Then; se un nuovo tipo è stato definito,
If DefinisceLivello (sNomeTipo, iLivello) Then; se viene scelto anche un livello,
Return TRUE; restituisce l’esito positivo
Else; altrimenti, se la scelta è stata annullata,
Let sNomeTipo = NULLO; cancella il dato
EndIf; fine controllo scelta livello
EndIf; fine controllo impostazione tipo
Return FALSE; se nessun altro controllo è intervenuto, restituisce un risultato nullo
EndFunction

Esercizio 7.3.7. La funzione CancellaChiave.

FileScript.

Default.JSS

Nome.

CancellaChiave

Descrizione.

Cancella l’eventuale dato della chiave nella sezione specificata, nel file di configurazione del tipo indicato.

Ritorni.

Di tipo Int. L’esito della cancellazione: TRUE per la riuscita, FALSE per il fallimento.

Parametri.
  1. iTipo. Il valore numerico corrispondente all’archivio da impostare. Di tipo Int.
  2. sSezione. L’etichetta della sezione nell’archivio di cui elaborare i dati. Di tipo String.
  3. sChiave. La chiave del dato da cancellare. Di tipo String.
Novità.
  1. La funzione integrata
    IniRemoveKey
    , (CancellaChiaviNeiFileIni), che serve appunto a cancellare un dato con la sua chiave. Ha anch’essa tre parametri, seppure posizionati nell’ordine diverso:
    • La sezione da cui cancellare il dato.
    • La chiave del dato da rimuovere.
    • Il nome dell’archivio in cui operare.
Note.

Analogamente alla precedente che leggeva le chiavi di una sezione, la funzione serve unicamente a chiamare quella integrata
IniRemoveKey ()
, guadagnando in leggibilità e semplificando il modo di individuare il nome dell’archivio.

Codice.


Int Function CancellaChiave (int iTipo, string sSezione, string sChiave)
Return IniRemoveKey ( ; cancella il dato della chiave specificata
sSezione, ; parametro1, nome della sezione in cui cercare il dato
sChiave, ; parametro2, chiave del dato da rimuovere
NomeArchivio (iTipo)); parametro3, nome dell’archivio del tipo specificato
EndFunction

Esercizio 7.3.8. La funzione ControllaScritturaCodice.

FileScript.

Default.JSS

Nome.

ControllaScritturaCodice

Descrizione.

Chiede conferma prima di avviare la scrittura dei dati rilevati per la finestra al livello preimpostato, e ne ritrasmette l’esito.

Ritorni.

Di tipo Int. L’esito della registrazione: TRUE, in caso di conferma; FALSE, per un risultato nullo.

Parametri.
  1. sNomeTipo. Il nome assegnato alla tipologia di finestre di cui rilevare i dati. Di tipo String.
  2. sCodice. La stringa che rappresenta il codice identificativo personale della finestra di cui leggere i dati. Di tipo String.
Novità.
  1. Nella funzione integrata
    ExMessageBox ()
    , stavolta useremo il tipo di conferma a tre opzioni, con in più anche
    Annulla
    , ponendo la costante nativa
    MB_YESNOCANCEL
    , quindi cambiando anche la relativa icona, tramite
    MB_USERICON.
  2. La costante
    NESSUNO
    , che serve a salvare una stringa nulla al posto del codice identificativo, così da far fallire tutti i successivi confronti.
Fasi.
  1. Tramite la funzione
    ExMessageBox ()
    , si determina se proseguire o meno la registrazione del codice identificativo personale per la finestra al livello specificato.
  2. Una struttura di controllo gestisce il valore restituito dalla richiesta di conferma, attivando la scrittura del codice nel caso in cui si scelga il pulsante

    o si prema
    Ok
    o la lettera
    "S".
  3. Nel caso si scelga
    No
    , o si prema la lettera
    "N"
    ,si procede al salvataggio di una stringa nulla, per creare comunque un dato di confronto e far fallire i successivi controlli.
  4. Se invece si preme Escape, o il pulsante
    Annulla
    , si esce dalla procedura guidata senza apportare modifiche ai valori eventualmente registrati.

Codice.


Int Function ControllaScritturaCodice (string sNomeTipo, string sCodice)
Var
String sMessaggio, ; il testo da presentare a video
Int iTasto; il tasto premuto
; formatta il messaggio base aggiungendo tipo finestra e nome applicativo
Let sMessaggio = FormatString (msgConfermaDati, sNomeTipo, GetActiveConfiguration ())
Let iTasto = ExMessageBox ( ; chiede conferma alla scrittura del codice
sMessaggio, ; parametro1, il testo per la casella di sola lettura
ttlConfermaDati, ; parametro2, titolo della schermata
MB_YESNOCANCEL|MB_USERICON); parametro3, tipo di conferma e icona di avviso
If iTasto == IDYES Then; se si è confermata la registrazione del codice identificativo,
Return ScriveCodiceFinestra (sNomeTipo, sCodice); tenta la scrittura e ne restituisce l’esito
ElIf iTasto == IDNO Then; se invece si è scelto di non confermarla tramite l’omonimo pulsante,
ScriveCodiceFinestra (sNomeTipo, NESSUNO); inibisce ulteriori controlli per l’applicazione
EndIf; fine controllo conferma
Return FALSE; se non si conferma la scelta, si restituisce comunque un risultato nullo
EndFunction

Esercizio 7.3.9. Lo script DefinisceTipiFinestra.

FileScript.

Default.JSS

Nome.

DefinisceTipiFinestra

Sommario.

Sceglie un tipo di finestra esistente, o ne crea uno di nuovo.

Descrizione.

Consente di selezionare tra i tipi di finestra registrati quello da applicare alla finestra corrente, registrandone i dati nei file di configurazione. Nel caso non esista, permette di creare un nuovo tipo, scegliendone anche il livello. Nel caso di impostazioni non valide, consente altresì di sovrascrivere i dati già memorizzati o di cancellare precedenti registrazioni.

TastiAttivazione.

Control+Windows+I

Novità.
  1. Il primo utilizzo della nostra funzione
    LeggeChiavi ()
    , con due costanti usate come parametri.
  2. La prima volta anche per
    NuovoTipoFinestra ()
    , con il valore relativo al livello trasmesso per riferimento.
  3. Esordio infine per il nostro ultimo lavoro,
    ControllaScritturaCodice ()
    , che nel suo secondo parametro usa l’altra nostra funzione
    CodiceFinestra ().
Fasi.
  1. Rileva l’elenco dei tipi di finestra registrati nel file di configurazione Personale, tramite la nostra funzione
    LeggeChiavi ().
  2. Se dei tipi sono stati già registrati, consente di selezionarne uno dall’elenco, cui è stata aggiunta la voce per sceglierne uno di nuovo, tramite la funzione integrata
    DlgSelectItemInList ().
  3. Se è stato scelto di impostare un nuovo tipo di finestra, oppure se non ne è ancora stato registrato alcuno, viene attivata la procedura di creazione di un nuovo tipo tramite la nostra funzione
    NuovoTipoFinestra ().
  4. Se in ogni caso un tipo è stato scelto, tenta di registrarne i dati, restituendone l’esito, grazie alla nostra funzione
    ControllaScritturaCodice ().
  5. Se invece nessun tipo è stato scelto, restituisce un risultato nullo.
Note.
  1. Una volta confermata una scelta con
    DlgSelectItemInList ()
    , il nome del tipo di finestra viene impostato usando la funzione integrata
    StringSegment ()
    , che estrae dall’elenco la voce scelta, purché non sia l’ultima.
  2. I tasti di attivazione proposti sono di facile memorizzazione, usando la lettera iniziale del nome, poiché di questo script se ne potrà fare un uso frequente. Inoltre, se ricordate, essi sono una semplificazione dei tasti che attivavano lo script informativo sulle finestre, che si attiva con la stessa combinazione premendo in più il tasto
    Shift.

Codice.


Script DefinisceTipiFinestra ()
Var
String sElenco, ; elenco tipi di finestra registrati
Int iScelta, ; scelta effettuata
String sNomeTipo, ; il tipo di finestra scelto
Int iLivello; il livello di finestra di cui rilevare i dati
Let sElenco = LeggeChiavi (PERSONALE, TIPI_FINESTRE); rileva l’elenco delle voci
If sElenco Then; se sono stati rilevati dei tipi di finestra,
Let sElenco = sElenco + PIPE + lstNuovoTipo; aggiunge la voce per sceglierne una nuova
; Consente di scegliere un tipo di finestra esistente o di impostarne uno nuovo
Let iScelta = DlgSelectItemInList (sElenco, ; parametro1, elenco delle scelte possibili
FormatString (ttlTipiFinestre, lstNuovoTipo, msgInfoScelte), ; parametro2, messaggio
FALSE);parametro3, ordinamento alfabetico disattivato
If iScelta == FALSE Then; se non è stata impostata alcuna scelta,
Return; interrompe il flusso
ElIf iScelta < StringSegmentCount (sElenco, PIPE) Then; se la voce scelta non è l’ultima
Let sNomeTipo = StringSegment (sElenco, PIPE, iScelta); estrae la voce dall’elenco
Let iLivello = LeggeLivelloFinestra (sNomeTipo); rileva il livello salvato per il tipo di finestra
EndIf; fine controllo scelta
EndIf; fine controllo tipi registrati
If !sNomeTipo Then; se il tipo di finestra non è stato definito,
NuovoTipoFinestra (sNomeTipo , iLivello); imposta, e trasmette, tipo e livello della finestra
EndIf; fine controllo presenza dato
If sNomeTipo Then; se un tipo di finestra è impostato,
If ControllaScritturaCodice (sNomeTipo, CodiceFinestra (iLivello)) Then; se i dati si salvano,
Return TRUE; restituisce l’esito positivo
EndIf; fine controllo scrittura
EndIf; fine controllo tipo finestra
Return FALSE; se nessun altro controllo è intervenuto, restituisce un risultato nullo
EndScript

Collaudo.

In questo script sono coinvolte parecchie funzioni, molte delle quali realizzate da noi. Nessun timore, quindi, se si verificassero degli errori in fase di compilazione.

Come al solito, provate ad interpretare i messaggi d’errore proposti, oppure cancellate lo script e ripetete i passaggi.

Quando tutto andrà bene, proviamo lo script per registrare due nuovi tipi di finestra.

Questa esigenza nasce dal fatto che con la dicitura
Editing
, che abbiamo usato nel nostro primo esempio, si potrebbero accumunare le finestre primarie di tutti gli applicativi che abbiamo usato sinora.

Pertanto, vorremmo fare un’ulteriore suddivisione dentro a questi applicativi, creando due nuovi tipi di finestra, che corrispondono ad altrettante sottocategorie:

  1. Quella degli applicativi dove il cursore è rilevato tramite il numero di riga.
  2. Quella dei programmi in cui il cursore ha una posizione assoluta, che corrisponde al numero di caratteri dall’inizio del documento.

Nel primo caso, registreremo un nuovo tipo di finestra dentro al Blocco Note di Windows, nel secondo lo imposteremo tramite Microsoft Wordpad. Provate quindi a seguire questi passi:

  1. Entrate nel Blocco Note, con un documento anche vuoto, ed eseguite lo script
    DefinisceTipiFinestra ()
    , con la combinazione
    Control+Windows+I.
  2. Si presenterà un elenco formato da due voci,
    Editing
    e
    Immetti nuovo tipo
    . Poiché la scelta che ci serve non c’è, selezioniamo e poi confermiamo la seconda.
  3. Nella casella di inserimento che si presenterà, scriviamo la parola
    "Righe"
    , senza specificare le virgolette, termine che avevamo registrato nell’omonima costante ad inizio capitolo, e poi confermiamo con Invio.
  4. Alla richiesta del livello a cui leggere i dati, confermiamo la scelta selezionata,
    Corrente
    , dopodiché si dovrebbe essere avvisati che i dati sono stati salvati.
  5. Alla richiesta se quella in cui è stato attivato lo script sia la finestra denominata
    Righe
    per l’Editor di Script, confermate con Invio oppure premete la lettera
    "S"
    , e dovreste sentire la definitiva conferma dell’avvenuto salvataggio dei dati.
  6. Adesso, se riaprite il nostro file di configurazione Personale, troverete registrato anche questo secondo tipo di finestra, che poi ritroveremo più avanti. Uscite ora dal Blocco Note, ed aprite Microsoft Wordpad.
  7. Da Dentro la finestra principale del programma, eseguite ancora lo script d’impostazione, premendo
    Control+Windows+I
    . Nell’elenco delle voci possibili, come detto, troverete anche la voce appena inserita, ma voi scegliete e confermate ancora
    Immetti nuovo tipo.
  8. Nella casella di editazione che si apre, stavolta digitate il termine
    "Posizione"
    , anch’esso già registrato nell’omonima costante, e confermate con Invio.
  9. Rispondendo alle richieste della procedura, operate le stesse scelte dei punti 4 e 5, completando la procedura d’impostazione del tipo di finestra.
  10. Chiudete anche Wordpad, e tornate all’Editor di Script.

***

Il controllo sulle finestre.

Ora, grazie allo script appena realizzato, siamo perciò in grado anche di creare le condizioni affinché un controllo sulle finestre sia possibile. Manca quindi solo l’elemento di codice che, nel nostro caso, sarà una funzione, la quale rappresenterà d’ora in avanti uno dei nostri strumenti più utilizzati.

Se ricordate, nello scorso capitolo ci eravamo già posti una domanda, alla quale un nostro controllo avrebbe dovuto saper rispondere. Sarà quindi sufficiente creare una funzione che sia la risposta a tale domanda, la quale restituisca un valore
TRUE
o
FALSE
. Tale valore ci consentirà, rispettivamente, di proseguire o meno il flusso dello script, tramite una struttura di controllo
If-
Then.

Come preannunciato, tale funzione potrà anche attivare i sistemi di registrazione dei dati necessari al suo funzionamento, come ad esempio il livello a cui leggere il tipo di finestra specificato ed il relativo codice di identificazione personale. Tale attivazione non sarà mai automatica, ma potrà essere avviata da una fase di supporto che saremo comunque noi ad attivare, come illustreremo durante il collaudo.

Esercizio 7.4.1. La funzione SiamoNellaFinestra.

FileScript.

Default.JSS

Nome.

SiamoNellaFinestra

Descrizione.

Controlla se la finestra attiva corrisponde a quella del tipo specificato come parametro, e memorizzata nell’archivio dell’applicazione corrente. Nel caso in cui tale archivio non contenga alcun codice che corrisponda al tipo di finestra da confrontare, qualora sia stato valorizzato l’apposito parametro opzionale, sarà avviata una procedura guidata di registrazione dei dati mancanti.

Ritorni.

Di tipo Int. L’esito del confronto tra i codici: TRUE per un riscontro positivo, FALSE per un risultato nullo.

Parametri.
  1. sNomeTipo. Il tipo di finestra da confrontare. Di tipo String.
  2. iAiuto. Se contiene un valore positivo, avvia la procedura per il completamento dei dati necessari alla funzione stessa. Di tipo Int. Parametro Opzionale.
Novità.
  1. La presenza di un parametro opzionale. Questa particolarità non cambia nulla in fase di inserimento tramite la procedura guidata, nel modo di creare la funzione, ma obbliga ad una particolare modifica, successiva alla compilazione, a cui sarà dedicato il prossimo titolo.
  2. La comparsa di una modalità di funzionamento, denominata
    Fase Aiuto
    , in cui si attivano messaggi e controlli suppletivi nelle nostre procedure che consentono sia di avere maggiori informazioni, sia di avviare procedure interattive di conferma o creazione dati da registrare. Più avanti, nel collaudo di questa funzione, sarà illustrato nel dettaglio cosa prevede tale fase durante la gestione dei controlli alle finestre.
Fasi.
  1. Dopo il tentativo di rilevare il livello abbinato al tipo di finestra da controllare, una prima struttura di controllo gestisce l’eventuale aggiornamento del valore tramite la nostra funzione
    DefinisceLivello
    , solo nel caso sia attiva la fase aiuto. Se così invece non è, nel caso siano già stati salvati dei dati per le finestre nell’applicazione corrente, viene letto per una volta un avviso che invita a registrare i dati necessari.
  2. Dopo il tentativo di rilevare il codice identificativo della finestra, una seconda struttura verificherà la presenza di entrambi i codici da confrontare, e poi se siano uguali. In caso positivo, il flusso si interromperà restituendo l’esito favorevole.
  3. Se il flusso giunge alla terza ed ultima struttura di controllo, qualora sia stato specificato il secondo parametro, si avvia la Fase Aiuto, con la procedura di registrazione dei dati mancanti della finestra.
  4. Nel caso di avvenuta registrazione, si ritenta il confronto e, in caso positivo, viene restituito un valore TRUE.
  5. Infine, se la Fase Aiuto non è attiva, o se comunque la registrazione dei dati è stata interrotta, viene restituito un risultato nullo.
Note.
  1. Le strutture di controllo sono state rese le più semplici possibile grazie all’utilizzo di funzioni che restituiscono un valore TRUE o FALSE, per far proseguire o meno il flusso. Eventuali dati che dovevano essere passati alla funzione chiamante, sono stati trasmessi
    per riferimento.
  2. Ricapitolando, la funzione fa partire eventuali procedure guidate, o pronuncia dei messaggi, quando risulti attiva la modalità Aiuto, specificando il secondo parametro che abbiamo detto essere
    Facoltativo.
  3. Come detto, l’unica eccezione in tal senso è rappresentata dall’avviso relativo alla mancata definizione di un livello per un tipo di finestra. Tale avviso può essere infatti letto a prescindere dalla fase Aiuto, ma solo nel caso in cui siano già stati registrati manualmente degli altri dati sulle finestre per l’applicativo corrente. Ciò avviene, inoltre, solo la prima volta poiché, dopo tale passaggio, il nome della finestra viene registrato nella variabile globale, impostazione che ne impedisce eventuali successive letture in sequenza.

Codice.


Int Function SiamoNellaFinestra (string sNomeTipo, int iAiuto)
Var
Int iLivello, ; il livello della finestra di cui leggere i dati
String sCodiceConfronto ; il dato registrato da confrontare
; Rileva il livello del tipo di finestra specificato
Let iLivello = LeggeLivelloFinestra (sNomeTipo)
If !iLivello Then; se il livello non è stato ancora registrato,
If !iAiuto Then; se non è attiva la fase,
If LeggeChiavi (CORRENTE, DATI_FINESTRE) ; se sono salvati dei dati per le finestre,
&& gsNomeFinestra != sNomeTipo Then; e se un messaggio non è già stato letto,
SayFormattedMessage (OT_ERROR, hlpNoLivello, NULLO, sNomeTipo); avvisa dell’errore,
Let gsNomeFinestra = sNomeTipo; poi evita la ripetizione immediata del messaggio
EndIf; fine controllo registrazione dati
Return FALSE; interrompe il flusso, restituendo un risultato nullo
ElIf !DefinisceLivello (sNomeTipo, iLivello) Then; anche se un livello non viene poi scelto,
Return FALSE; si interrompe il flusso
EndIf; fine controllo Aiuto
EndIf; fine controllo presenza livello
; rileva il dato registrato per l’applicativo corrente
Let sCodiceConfronto = LeggeCodiceFinestra (sNomeTipo)
If sCodiceConfronto Then; se un dato è stato rilevato,
If CodiceFinestra (iLivello) == sCodiceConfronto Then; se i due codici corrispondono,
Return TRUE; restituisce l’esito positivo
ElIf sCodiceConfronto == NESSUNO Then; se invece il codice è quello di annullamento,
Return FALSE; interrompe il flusso restituendo un valore nullo
Else; altrimenti, se il confronto fallisce,
If iAiuto Then; se è attiva la fase,
SayMessage (OT_ERROR, hlpNoFinestra, hlpNoFinestra_corto); legge l’avviso
EndIf; fine controllo aiuto
Return FALSE; in ogni caso, interrompe il flusso restituendo un risultato nullo
EndIf; fine controllo confronto
EndIf; fine controllo presenza codice
If iAiuto Then; se è attiva la fase,
Return ControllaScritturaCodice (sNomeTipo, CodiceFinestra (iLivello)); chiede conferma
Else; altrimenti, dato che il controllo è fallito,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo aiuto
EndFunction

Collaudo.

Salvate e compilate il lavoro ma, come preannunciato, dovremo subito intervenire per far si che il secondo parametro si possa eventualmente specificare. Siccome un tale argomento è di carattere generale , e non legato quindi al collaudo di questa funzione, vi dedicheremo il prossimo titolo, dopo del quale potrete procedere al salvataggio del nostro lavoro.

Rendere opzionale il parametro di una funzione.

Dovrebbe essere oramai chiaro che per
Opzionale
si intende un parametro che possa essere specificato oppure no. In genere, un tale parametro prevede comunque un suo valore predefinito, oppure un comportamento che l’elemento di codice cui è stato aggiunto assuma in ogni caso anche in sua assenza.

Purtroppo, non è possibile definire che un parametro sia opzionale durante la procedura di creazione guidata. Una volta compilato il codice, quindi, sarà necessario modificare a mano il
file di Documentazione
, quelli con l’estensione
JSD
, inserendo una speciale parola chiave .

A tale scopo, appare opportuno analizzare brevemente la struttura di questi speciali file, eseguendo poi la modifica necessaria. Provate quindi a seguire questi passi:

  1. Aprite la cartella dei file dell’Utente con
    Control+O
    , quindi scendete fino a selezionare il tipo
    File di documentazione (*.jsd).
  2. Tornati alla casella di elenco, premete la lettera
    D
    per selezionare e poi confermare il file
    Default.JSD.
  3. Con la funzione di ricerca testo,
    Control+F
    , cercate il nome della funzione,
    SiamoNellaFinestra.

Proponiamo di seguito quanto potrebbe essere il contenuto della sezione del file che riguarda tale nostra funzione:


:Function SiamoNellaFinestra
:Returns int L’esito del controllo: TRUE per finestra corretta, FALSE per mancato riscontro.
:SearchRank 1
:Category _Ps
:Param string/sNomeTipo Il tipo di finestra da confrontare.
:Param int/iNoAuto Impedisce, se posto a TRUE, di avviare la procedura di registrazione.

Come potete notare, i dati della funzione sono posti ciascuno su una riga. Ogni dato è preceduto da una parola chiave, a sua volta preceduta da un carattere Due Punti.

Analizzandole nel dettaglio, l’iscrizione
SearchRank
, (CategoriaDiRicerca), è un dato fisso,mentre dopo la parola chiave
:Category
, (Categoria), si troverà quella da voi eventualmente selezionata o immessa durante la creazione guidata, che in questo esempio è rappresentata dal nostro classico prefisso.

La parte che a noi interessa è quella appunto dei parametri, dove ciascuno di essi è preceduto dalla parola chiave
Param
. Dopo di questa, il primo termine che precede il carattere Barra,
/
, è il tipo di dato. Proseguendo, almeno in questo caso, si troverà il nome del parametro seguito dalla sua descrizione. Per completezza, va detto che, qualora il parametro sia
per riferimento
, tra il tipo ed il nome sarebbe posta la parola chiave
ByRef.

Tornando alla modifica da compiere, tutto quello che dobbiamo fare è scrivere la parola chiave
:Optional
, inserendola in una riga a sé stante che precede quella del parametro da cui vogliamo far partire quelli opzionali.

Nel nostro caso, la sezione della nostra funzione diventerebbe questa:


:Function SiamoNellaFinestra
:Returns int L’esito del controllo: TRUE per finestra corretta, FALSE per mancato riscontro.
:SearchRank 1
:Category _Ps
:Param string/sNomeTipo Il tipo di finestra da confrontare.
:Optional
:Param int/iNoAuto Impedisce, se posto a TRUE, di avviare la procedura di registrazione.

Una volta inserita tale iscrizione, non vi resta che salvare le modifiche e chiudere il file aperto con
Control+F4
, tornando al file script Predefinito.

Qui, compilate nuovamente, ed il gioco dovrebbe essere fatto. Attenzione, però: non essendo una funzionalità gestita direttamente dall’Editor di script, può capitare a volte che tale impostazione risulti cambiata, qualora si apportino successive modifiche alla funzione che la prevede. In genere, si consiglia di effettuare la modifica sul file di documentazione, compilare con successo il file script che contiene la funzione con il parametro opzionale, quindi uscire dall’Editor di Script per salvare definitivamente tale modifica.

Inoltre, quando si modifica in un secondo momento una funzione tramite il comando
Control+D
, se tale funzione avesse dei parametri fissi ed almeno uno opzionale, può pure capitare che la parola chiave
:Optional
si sposti ad inizio dell’elenco dei parametri, rendendoli così tutti opzionali. Questa variazione di per sé può anche non creare problemi, e potreste persino non accorgervi della cosa. Se necessario, tuttavia, si può sempre tornare ad aprire il file Documentazione, spostando poi la parola chiave nella posizione corretta, quindi salvare di nuovo per ripristinare la situazione precedente.

Attivare un parametro direttamente dalla tastiera.

Nel controllo sulle finestre da noi realizzato, la funzione che lo gestisce ha due parametri, di cui il secondo abbiamo appena esaminato come renderlo opzionale. Se ricordate, tale secondo parametro, denominato
iAiuto
, già dal suo nome ci ricorda come esso indichi lo stato di attivazione dell’omonima fase.

La fase
Aiuto
, come già annunciato, è una modalità interattiva che in questo controllo svolge principalmente due ruoli:

  1. Pronuncia tutti i messaggi di supporto alla procedura.
  2. Nel caso che dei dati sulle finestre siano mancanti, chiama le funzioni che ci consentono di aggiornarli direttamente.

Così, quando nella chiamata del nostro controllo,
SiamoNellaFinestra ()
, specifichiamo un valore positivo come secondo parametro, negli script e nelle funzioni che lo contengono sono letti tutti i messaggi, e casomai sarebbe fatta partire la procedura di aggiornamento dati. Al contrario, se non si specifica nulla, nessun messaggio ci sarà pronunciato, e soprattutto non ci sarà possibile da lì impostare alcun dato sulle finestre.

In altre parole, servirci sempre della prima opzione potrebbe sembrare più conveniente, ma ciò può far intervenire la procedura anche quando non dovrebbe. D’altro canto, non usare mai il secondo parametro ci toglierebbe invece tutta la parte interattiva della procedura, sebbene più avanti nel capitolo dedicheremo un intero argomento per spiegare l’unico caso in cui la scelta di non mettere nulla è indispensabile.

Il giusto compromesso, fra tutto o niente, ci è fornito da un’interessante funzione integrata di Jaws,
IsSameScript
, che si traduce (E’LoStessoScript). Essa, infatti, restituisce un valore TRUE quando si preme due volte in successione la combinazione di tasti che attiva lo script, ed è senza parametri.

In pratica, il suo funzionamento è lo stesso di quando, attivando la
Modalità Aiuto Tastiera
con
TastoJaws+1
, si premono due volte in rapida successione i tasti relativi ad uno script per conoscerne la descrizione dettagliata. Nei prossimi esercizi ne esamineremo un esempio, che potrà rendere più chiaro il suo funzionamento.

La versione definitiva del controllo sulle Finestre.

Nello scorso capitolo avevamo preannunciato che il nostro obiettivo sarebbe stato creare un unico controllo che potesse verificare se si fosse nella finestra corretta. Siccome quella che abbiamo denominato
Editing
è una finestra piuttosto comune, la inseriremo nel nostro primo controllo, il quale varrà per tutti i quattro applicativi principali in cui abbiamo operato sinora.

Esaminate la seguente condizione:


If SiamoNellaFinestra (EDITING) Then

Come potete notare, utilizzando la nostra ultima funzione, abbiamo ora realizzato la forma definitiva del controllo. A questa forma, per determinarne il funzionamento, sarà quindi sufficiente di volta in volta modificare il nome del tipo di finestra da verificare, ponendolo come primo parametro, e valutare se mettere qualcosa come secondo parametro, casomai la funzione speciale citata in precedenza.

Come spiegazione, il nome in italiano della funzione non rende nemmeno necessari troppi commenti: se ci si trovasse nella finestra corretta, nel caso dell’esempio quella denominata
EDITING
, allora il controllo restituirà un valore
TRUE
, altrimenti un
False.

Per testare questa forma del controllo, prenderemo spunto da elementi di codice realizzati ancora nel terzo capitolo, creando una coppia di script che renderà più facilmente accessibili i comandi di ripetizione della ricerca. Questi comandi si trovano di solito nel menu
Modifica
, come ad esempio nell’Editor di Jaws, e comunque si attivano con il tasto
F3
, per la ricerca del termine successivo, e
Shift+F3
, per la ricerca di quello precedente.

Poiché questi tasti si trovano tutti a lato della tastiera, faremo sì che li si possa eseguire con una combinazione tasti più comoda,
Control+PaginaGiù
e
Control+PaginaSu
rispettivamente. Tali combinazioni, tra l’altro, rappresentano le stesse scelte rapide usate anche ad esempio in Microsoft Word per ripetere l’ultima ricerca in avanti o all’indietro, creando così una continuità di gesti anche con questo importante programma.

in questi due casi, il nome del tipo di finestra da verificare nel nostro controllo sarà lo stesso usato nella forma analizzata, perché le scelte rapide
F3
e
Shift+F3
rappresentano uno standard abbastanza diffuso in particolare negli editor testuali, e comunque negli applicativi dove poter scrivere. Inoltre, come secondo parametro metteremo proprio la funzione integrata
IsSameScript ()
, con la quale potremo far partire la procedura di settaggio interattivo solo nei casi in cui questo sarà necessario.

Esercizio 7.4.5. Lo script CercaRipetiSuccessivo.

FileScript.

Default.JSS

Nome.

CercaRipetiSuccessivo

Sommario.

Ripete l’ultima ricerca in avanti.

Descrizione.

Cerca la successiva occorrenza del testo inserito nell’ultima ricerca effettuata.

TastiAttivazione.

Control+PaginaGiù

Novità.
  1. La nostra funzione
    SiamoNellaFinestra ().
  2. La funzione integrata
    IsSameScript ()
    , illustrata in precedenza.
  3. La costante
    F3
    , che corrisponde all’omonima scelta rapida per la ripetizione della ricerca in avanti.
Note.
  1. Oltre al più volte citato controllo sulle finestre, e all’ovvio richiamo della scelta rapida originale, lo script contiene in più solo una istruzione
    SayLine ()
    , che serve appunto per leggere la riga in cui si ferma il cursore dopo la ricerca. Qualora nella vostra configurazione tale lettura automatica fosse già prevista, sarà sufficiente eliminare questo comando.

Codice.


Script CercaRipetiSuccessivo ()
If SiamoNellaFinestra (EDITING, IsSameScript ()) Then; se si è in una finestra di editazione,
TypeKey (F3); richiama il comando originale
Pause ()
SayLine (); legge la riga corrente
Else; altrimenti, se non si tratta della finestra corretta,
TypeCurrentScriptKey (); ripete i tasti di attivazione dello script
EndIf; fine controllo finestra
EndScript

Collaudo.

Se la compilazione va a buon fine, spostiamo il test al prossimo script, che completa la coppia di elementi simili e, per certi versi, complementari.

Esercizio 7.4.6. Lo script CercaRipetiPrecedente.

FileScript.

Default.JSS

Nome.

CercaRipetiPrecedente

Sommario.

Ripete la ricerca all’indietro.

Descrizione.

Cerca la precedente occorrenza del testo inserito nell’ultima ricerca effettuata.

TastiAttivazione.

Control+PaginaSu

Novità.
  1. La costante
    SHIFT_F3
    , che corrisponde all’omologa scelta rapida per la ripetizione della ricerca all’indietro.

Codice.


Script CercaRipetiPrecedente ()
If SiamoNellaFinestra (EDITING, IsSameScript ()) Then; se si è in una finestra di editazione,
TypeKey (SHIFT_F3); richiama il comando originale
Pause ()
SayLine (); legge la riga corrente
Else; altrimenti, se non si tratta della finestra corretta,
TypeCurrentScriptKey (); ripete i tasti di attivazione dello script
EndIf; fine controllo finestra
EndScript

Collaudo generale del controllo sulle finestre.

Siamo quindi giunti finalmente al collaudo di tutti gli aspetti dei controlli sulle finestre. Pertanto, se la compilazione va bene, portatevi nell’Editor di Jaws, con caricato anche il file script Predefinito. Ricordiamo che per la finestra principale di questo Programma, eseguendo in precedenza lo script di Prova, abbiamo già registrato i dati necessari al funzionamento della procedura, che sono i seguenti:

  1. L’esistenza di un tipo di finestra denominato
    Editing.
  2. Il livello a cui leggere i dati per questo tipo di finestra, che è quello
    CORRENTE
    , di valore 1.
  3. Il codice relativo alla finestra principale del programma, che è quello da voi registrato nel capitolo scorso, e che adesso invece è stato scritto dalla funzione creata appositamente.

Ora, dopo aver fatto questo breve ma necessario riepilogo, provate a seguire questi passi:

  1. Eseguite la ricerca di un testo di cui siete sicuri vi siano diverse occorrenze, come ad esempio
    script.
  2. Eseguite lo script di ripetizione della ricerca in avanti, con
    Control+PaginaGiù
    . Poiché i dati registrati coincidono con la finestra dove ci troviamo, il nostro controllo restituirà il valore TRUE. Così facendo, il flusso entrerà nella struttura di controllo nello script, e farà quindi simulare a Jaws la pressione della scelta rapida
    F3
    . All’arrivo alla successiva occorrenza del termine, il contenuto della riga sul cursore vi dovrebbe essere letta.
  3. Provate quindi anche l’altro script con
    Control+PaginaSu
    . Dovreste tornare alla precedente occorrenza del termine, sempre con la riga sul cursore pronunciata da Jaws.
  4. Conclusa la prova nell’Editor di Jaws, aprite ora il Blocco Note, con un documento di una certa dimensione. Anche lì effettuate la ricerca di un termine che abbia più d’una occorrenza.
  5. Ora, eseguite da lì lo script per la ricerca in avanti, con
    Control+PaginaGiù
    . Siccome, diversamente da prima, i dati per una finestra del tipo
    Editing
    nel Blocco Note non sono ancora stati registrati, la procedura non li trova e, non essendo al momento attuale attivata la fase Aiuto, lo script non avrà alcun effetto.
  6. Provate allora a premere due volte velocemente i tasti di attivazione dello stesso script. Questa volta, poiché la doppia pressione fa assumere alla funzione
    IsSameScript ()
    un valore TRUE, essendo che tale funzione è specificata come secondo parametro, viene così attivata la fase Aiuto che, in mancanza di dati registrati, fa partire la procedura di impostazione interattiva.
  7. La procedura dovrebbe così visualizzare una finestra di dialogo, che vi chiederà:
  8. "Confermate l’attuale come finestra Editing per notepad?"

  9. Premendo Invio, o la lettera
    "S"
    , si sarà dapprima avvisati che i dati sono stati salvati, poi il flusso nello script dovrebbe proseguire ed entrare nella struttura di controllo, dove simulare finalmente il comando di ricerca per poi portarsi sulla nuova occorrenza del termine. Anche in questo caso, la riga sul cursore dovrebbe esservi letta.
  10. Ora, se da dentro la finestra primaria del Blocco Note, ripetete la pressione di
    Control+PaginaGiù
    , il cursore si sposterà direttamente sulla successiva occorrenza del termine.
  11. Un’importante avvertenza: premendo
    Control+PaginaSu
    , i tasti di attivazione dello script per la ricerca in alto, il cursore si sposterà all’occorrenza precedente solo nel caso del nuovo Blocco Note messo a disposizione da Windows 10. Nel caso delle precedenti versioni di questo applicativo, infatti, la scelta rapida
    Shift+F3
    non è neppure presente, ma alla fine del prossimo capitolo avremo modo di rimediare a questa lacuna.
  12. Per fare un’altra prova, sempre nel Blocco Note, richiamate il comando
    Sostituisci
    , con
    Control+H
    . Entrerete nella finestra di dialogo omonima, che ovviamente non coincide con quella primaria. Se voi provate a premere
    Control+PaginaGiù
    per provare ad eseguire lo script di ripetizione ricerca, non vi sarà vocalizzato niente perché, essendo stato registrato il codice per la finestra
    Editing
    , e risultando diverso da quello rilevato nella finestra
    Sostituisci
    , il confronto fallisce senza restituire nulla. Infine, se invece provate a premere due volte velocemente
    Control+PaginaGiù
    , sarà letto un avviso che vi informa che la finestra attiva non è valida per quel comando.
  13. Per completare il collaudo, aprite adesso il programma Wordpad, con un documento anche vuoto, e provate da lì a premere nuovamente
    Control+PaginaGiù
    per eseguire lo script. Ancora una volta, come nel caso precedente, non sarà vocalizzato nulla, poiché pure qui non sono stati mai memorizzati dei dati del tipo
    Editing.
  14. Sebbene noi potessimo già ora registrare i dati per questa finestra, supponiamo non fossimo in realtà in una finestra corretta, facendo finta di attivare per errore la Fase Aiuto tramite la doppia pressione dei tasti di attivazione dello script. A questo punto dovrebbe riproporsi la stessa finestra di dialogo analizzata in precedenza. Non dovendo confermare i dati, proviamo a premere il tasto Escape per ritornare a Wordpad, e nulla sarà cambiato nella configurazione.
  15. Qui, premendo altre due volte velocemente
    Control+PaginaGiù
    , si tornerà infatti alla solita richiesta di conferma. Ancora non diamo il nostro assenso, tuttavia, ed anzi clicchiamo su
    No
    , oppure premiamo la lettera
    "N"
    . In questo caso sentirete ancora un avviso relativo a dati salvati, che però stavolta si riferiscono al contenuto della costante
    NESSUNO
    , che se ricordate serve a dire a Jaws che un dato è comunque registrato e, non avendo il formato dei codici personali, restituirà sempre un confronto errato. Se successivamente provate a premere ancora la combinazione due volte velocemente, infatti, non sarà vocalizzato nulla, perché il confronto è stato comunque annullato in modo permanente.
  16. Qualora, come in questo caso, si fosse per qualche motivo fatto una scelta errata, si dovrà richiamare lo script di impostazione , con
    Control+Windows+I
    , scegliendo in questo caso
    Editing
    come tipo di finestra, confermando poi la successiva richiesta, e così sovrascrivendo ogni precedente impostazione.
  17. Per concludere il discorso su Wordpad, va detto che qui la ricerca all’indietro non funziona, ne in Windows 10, né nei sistemi precedenti, perché la ricerca all’indietro è un’opzione che manca nella finestra
    Trova
    . In compenso, all’ultima ripetizione della ricerca in avanti che dovesse fallire, l’applicativo propone un avviso da poter solo confermare, dopo del quale la ricerca riprende dall’inizio.

***

Limitare l’ambito degli Script.

Già nello scorso capitolo, all’interno della nostra funzione
MetteTesto ()
, avevamo realizzato un controllo che consentiva l’azione di uno script solo nel caso in cui fosse eseguito dalla finestra primaria dell’Editor di Jaws. Ora che ci siamo dotati di un controllo più completo e versatile, tuttavia, non toccheremo per il momento quella funzione, che intanto svolge il suo lavoro, riservandoci di poterla perfezionare quando la riprenderemo in mano più avanti.

Ci sono altri due script da noi realizzati nel terzo capitolo , invece, che rimangono fortemente a rischio, dato che possono nella forma attuale lavorare solo dentro all’Editor di Script, ma non hanno ancora alcun controllo che ne regoli il funzionamento:
MuoveElementoSuccessivo ()
e
MuoveElementoPrecedente ().

Questi due script, che avevamo realizzato per duplicare nella parte bassa della tastiera i comandi di spostamento tra gli elementi di codice, sono piuttosto simili a quelli che abbiamo appena realizzato per rendere più comodi i comandi di ripetizione della ricerca. La grande differenza è che in quel caso gli script erano costruiti per essere usati in più applicativi, mentre qui dobbiamo accertarsi che svolgano un certo lavoro per uno soltanto di essi.

A dire il vero le novità non saranno molte, poiché la procedura preliminare è la stessa utilizzata in precedenza per creare i due nuovi tipi di finestra, dentro al Blocco Note ed a Wordpad. La ripeteremo, dunque, impostandola in termini anche generali, così da fare un esempio di come dovreste fare nel caso in cui vogliate stabilire voi, da zero, un vostro tipo di finestra da controllare.

Provate quindi a seguire questi passi:

  1. Dall’interno dell’applicazione a cui vogliamo restringere il controllo, in questo caso dall’Editor di Script, premete
    Control+Windows+I.
  2. Scegliete
    Immetti nuovo tipo
    , quindi inserite un nome che volete sia riservato a quella finestra in quella applicazione. Prendendo spunto dal nome originale inglese dell’applicativo, inseriamo il termine
    MANAGER.
  3. Selezionate il livello della finestra più appropriato per leggere i dati, in questo caso
    CORRENTE.
  4. Nella finestra di dialogo che si presenta di seguito, confermate quella attiva come valida per il tipo di finestra appena impostato , in questo caso
    Manager
    , e così chiudendo la procedura di impostazione e tornando all’Editor di Jaws.
  5. Aprite ora il file personale delle Costanti,
    _PsConst.JSH
    , ed inserite l’assegnazione che prevede come nome della costante quello che avete inserito come nome del tipo di finestra, portato in caratteri maiuscoli, e come contenuto il nome stesso. Nel caso attuale, la riga di codice sarà quindi la seguente:
  6. 
    MANAGER = "Manager", ; termine omonimo
    

  7. Salvate e chiudete il file delle Costanti, tornando al file script Predefinito.
  8. Qui salvate compilando, chiudendo in pratica la procedura di restrizione della finestra.

Fin qui abbiamo seguito la procedura guidata, come nelle precedenti impostazioni , e l’unica azione manuale resta l’assegnazione della costante relativa al termine usato per identificare il tipo di finestra. In realtà, non sarebbe neppure questo un passaggio obbligato, perché lo stesso risultato si otterrebbe se nel primo parametro del controllo noi avessimo usato il termine
"Manager"
tra virgolette. Come già detto, tuttavia, l’utilizzo delle costanti serve appunto anche a togliere per quanto possibile i caratteri Virgolette dal codice, e quindi si consiglia di compiere questa operazione in modo sistematico.

L’unica grande differenza, quella che rende in effetti esclusivo il controllo dentro ad un solo applicativo, è il fatto di non specificare nulla come secondo parametro nella funzione
SiamoNellaFinestra ()
, usando perciò la forma seguente:


If SiamoNellaFinestra (MANAGER) Then

Tale forma, escludendo la possibilità che sia impostato un secondo parametro con valore positivo, impedisce l’attivazione della Fase Aiuto, neppure tramite la doppia pressione dei tasti di attivazione degli script. Quindi, per tornare ai nostri due script, sarà sufficiente inserire questo controllo, all’inizio del codice in essi contenuto, per limitare il loro utilizzo solo all’interno dell’Editor di Jaws.

Approfittiamo di questa minima modifica per aggiungerne un’altra, facendo sì che, anche nel caso si esegua lo script fuori dalla finestra principale dell’Editor, esso provochi lo stesso uno spostamento del cursore. Per capire come fare ad ottenere questo risultato, è necessario proporre ora un’altra pillola teorica.

Eseguire degli script partendo dai tasti di attivazione.

Negli ultimi due script ci siamo concentrati soprattutto nel collaudare il nostro sistema dei controlli sulle finestre, ed abbiamo quindi volutamente evitato di porre troppa carne al fuoco. In realtà, se da un lato la nostra funzione
SiamoNellaFinestra ()
ci aiuta a non attivare gli script al momento sbagliato, c’è anche il problema di assicurarsi che, se non ci si trovasse nella finestra corretta, il flusso possa continuare come se i tasti premuti non fossero stati nemmeno intercettati, oppure eseguendo lo stesso una qualche azione.

Nello scorso capitolo avevamo affrontato questo aspetto, definendo
script trasparente
. L’elemento di codice che abbia queste caratteristiche. In quella occasione, così come nei due script appena realizzati, ci siamo limitati ad usare l’istruzione
TypeCurrentScriptKey ().

Se ricordate, in questo caso i tasti premuti sono soltanto passati all’applicativo corrente, o al Sistema Operativo, senza quindi più coinvolgere Jaws. In altre parole, ipotizzando di aver eseguito un controllo sulla finestra attiva, e che questo abbia avuto esito negativo, la sequenza degli eventi sarebbe la seguente:

  1. Noi premiamo un tasto, o una combinazione tasti, per attivare uno script.
  2. Il controllo nello script si accorge che la finestra attiva non è quella corretta per proseguire.
  3. Il flusso passa quindi ad un’istruzione che ripete i tasti premuti e li invia all’applicazione corrente, o al sistema operativo.

Se noi al punto 3 volessimo invece far tornare in causa Jaws, eseguendo uno script nativo del quale conosciamo soltanto i tasti da premere, avremmo due opzioni:

  1. Usare l’istruzione
    PerformScript
    ,che però ci obbliga a conoscere prima il nome dello script da eseguire, il quale deve essere fisso e scritto direttamente nel codice.
  2. Usare la funzione integrata
    PerformScriptByName
    , (EseguiScriptPerNome), che ci consente invece di poter inserire tale nome anche tramite delle variabili, il cui contenuto può a sua volta provenire da altre funzioni. Per concludere l’analisi di questa nuova funzione, basterà dire che in essa il nome dello script dovrà essere posto come primo parametro, e che i successivi sono tutti opzionali e possono contenere eventuali parametri che fossero da specificare durante l’esecuzione dello script.

Nel primo caso, per poter far funzionare la soluzione, noi dovremmo seguire questi passi:

  1. Entrare nell’Aiuto Tastiera di Jaws.
  2. Premere tre volte velocemente la combinazione tasti di cui vogliamo conoscere il nome dello script ad essi collegato, rilevandolo grazie alla lettura anche tramite lo spelling oppure, dopo essere usciti dall’Aiuto Tastiera, consultando la cronologia della sintesi.
  3. Inserire manualmente nel codice il nome dello script da eseguire, ponendolo appunto dopo il comando
    PerformScript.

Nel secondo caso, servendosi di
PerformScriptByName ()
, si ha invece il vantaggio di poter sempre eseguire l’eventuale script di Jaws abbinato ai tasti che vogliamo simulare, senza doverlo scrivere nel codice. Rimane, ovviamente, il problema di sapere a quale script siano abbinati determinati tasti, ma per questo Jaws ci fornisce una coppia di funzioni integrate:

  1. GetCurrentScriptKeyName
    , (OttieniNomeTastiScriptCorrente), che restituisce la stringa relativa ai tasti, o alla combinazione di tasti, premuti per attivare uno script. Questa semplice funzione non ha parametri, e quindi basterà assegnarne il valore ad una variabile per poter disporre di tale dato.
  2. GetScriptAssignedTo
    , (OttieniScriptAssegnatoA), che ci fa conoscere il nome di uno script specificando come suo unico parametro i tasti che lo attivano.

Dato il loro scopo, le due funzioni sono spesso utilizzate in coppia, in quanto la prima può direttamente fungere da parametro alla seconda.

Per aiutarci nella loro gestione, come spesso capita, realizzeremo subito una nostra funzione, che ci aiuti inoltre a determinare quando far ripetere gli ultimi tasti premuti.

Dato che ci siamo, tale funzione ci potrà anche pronunciare il nome dello script da noi attivato, oppure lasciare l’onere di vocalizzare il lavoro svolto direttamente allo script eseguito.

Una volta messo a punto tale strumento, potremo quindi utilizzarlo nella citata modifica degli script per lo spostamento agli elementi di codice successivo o precedente. Nel dettaglio, faremo sì che:

  1. Tali script siano eseguiti solo nel tipo di finestra che noi abbiamo registrato come
    Manager.
  2. In tutti gli altri applicativi, ci sarà comunque uno spostamento del cursore grazie alla nostra funzione, che in questo caso simulerà la pressione dei tasti
    Control+FrecciaGiù
    e
    Control+FrecciaSu
    , per passare, nell’ordine, al paragrafo successivo o al precedente.

In questo modo, noi potremo pian piano abituarci ad usare sempre le combinazioni che attivano i nostri script,
Windows+FrecciaGiù
e
Windows+FrecciaSu
, quando ci si debba spostare al successivo blocco di testo. Nel caso in cui ci si trovi nell’Editor di Jaws, quindi, ci si muoverà di un elemento di codice, mentre in tutti gli altri applicativi ci si sposterà, almeno per il momento, di un paragrafo.

Esercizio 7.5.2. La funzione PronunciaEsegue.

FileScript.

Default.JSS

Nome.

PronunciaEsegue

Descrizione.

Determina se eseguire lo script abbinato ai tasti specificati, oppure se ripetere la pressione degli ultimi tasti premuti.

Ritorni.

Di tipo Void. Nessuno.

Parametri.
  1. sTasti. Il tasto, o la combinazione tasti, abbinate allo script da eseguire. Di tipo String. Parametro Opzionale.
  2. iRipeti. Un valore,
    TRUE
    o
    FALSE
    , che consenta di forzare la ripetizione dei tasti specificati. Di tipo Int. Parametro Opzionale.
Novità.
  1. Le funzioni integrate
    PerformScriptByName (),
    GetCurrentScriptKeyName ()
    e
    GetScriptAssignedTo ()
    , tutte già presentate.
Fasi.
  1. La prima parte di una struttura di controllo verifica se siano stati indicati dei tasti come primo parametro, e se non sia stata impostata la ripetizione forzata di tali tasti. Se così è, esegue un nome di script abbinato ai tasti specificati, interrompendo poi il flusso.
  2. Nella seconda parte della struttura, si verifica dapprima che nessun tasto sia stato specificato, ed in tal caso sono memorizzati gli ultimi tasti premuti.
  3. Viene quindi simulata la ripetizione dei tasti impostati, a prescindere dalla loro provenienza.
  4. Se come secondo parametro era stato indicato un valore positivo, si forza la lettura del nome di script relativo agli ultimi tasti premuti, anziché quello abbinato ai tasti specificati.
  5. Se al termine dell’elaborazione vi sono dei tasti memorizzati, ne viene letto l’eventuale nome di script abbinato.

Codice.


Void Function PronunciaEsegue (string sTasti, int iRipeti)
If sTasti; se è sono stati specificati dei tasti,
&& !iRipeti Then; e non si è indicato alcun secondo parametro,
PerformScriptByName (GetScriptAssignedTo (sTasti)); esegue lo script abbinato ai tasti,
Return; e interrompe il flusso
EndIf; fine controllo esecuzione
If !sTasti Then; se non è stato indicato alcun tasto,
Let sTasti = GetCurrentScriptKeyName (); rileva gli ultimi tasti premuti
EndIf; fine controllo tasti
TypeKey (sTasti); invia i tasti all’applicazione o al sistema operativo
If iRipeti Then; se è stata impostata la forzatura della ripetizione tasti,
Let sTasti = GetCurrentScriptKeyName (); imposta i tasti solo per la lettura del nome script
EndIf; fine controllo ripetizione forzata
SayMessage (OT_ERROR, GetScriptAssignedTo (sTasti)); legge il nome del relativo script
EndFunction

Collaudo.

Se non ci sono problemi nella compilazione, pur ribadendo il rinvio del test all’ultimo elemento della procedura, invitiamo a rendere subito opzionale entrambi i parametri, ripetendo i passi già analizzati in precedenza, e che riproponiamo di seguito:

  1. Aprite il file di Documentazione
    Default.JSD
    , e cercate il nome della funzione,
    PronunciaEsegue.
  2. Portatevi all’inizio del primo parametro,
    sTasti
    , create una riga vuota ed inserite l’apposita parola chiave:
  3. 
    :Optional
    

  4. Salvate con
    Control+S
    , quindi Chiudete il file di Documentazione con
    Control+F4
    , tornando all’Editor, dove provate a compilare.
  5. Se non ci sono problemi, ricordiamo che conviene a questo punto uscire dall’Editor di Script per poi rientrarvi, così da rendere effettive le modifiche effettuate sui parametri opzionali.

Esercizio 7.5.3. La nuova versione di MuoveElementoSuccessivo ().

FileScript.

Default.JSS

Nome.

MuoveElementoSuccessivo

Descrizione.

Utilizzare la funzione nativa dell’Editor di Script per portarsi all’elemento di codice successivo, purché ci si trovi nell’Editor stesso. In tutti gli altri applicativi, viene eseguito lo script originale di Jaws abbinato alla combinazione di tasti per lo spostamento al paragrafo successivo.

Novità.
  1. La nostra funzione
    PronunciaEsegue ()
    , per la gestione del flusso in caso di finestra non corretta.
  2. Le costanti
    MANAGER,
    CONTROL_FRECCIAGIU
    e
    F2
    , che corrispondono, nell’ordine, al tipo di finestra da controllare, ed ai tasti per simulare, rispettivamente, l’esecuzione dello script per il passaggio al successivo paragrafo, e il comando dell’Editor con lo spostamento all’elemento successivo.
Note.

La modifica della forma originaria dello script prevede i seguenti passi:

  1. Inserire, nella riga appena sotto quella dell’intestazione, la seguente struttura di controllo:
  2. 
    If !SiamoNellaFinestra (MANAGER) Then; se non si è nella finestra corretta,
    PronunciaEsegue (CONTROL_FRECCIAGIU); attiva lo script di Jaws con i tasti indicati,
    Return; ed interrompe il flusso
    EndIf; fine controllo finestra
    

  3. Sostituire il comando tra parentesi Graffe con l’omologa funzione
    TypeKey ()
    , trasformando il nome dei tasti di cui simulare la pressione nella relativa costante, così come riportato nell’istruzione seguente:
  4. 
    TypeKey (F2); simula la pressione del tasto
    

  5. Come forse avete notato, stavolta l’istruzione con
    SiamoNellaFinestra ()
    viene posta in negativo, con il carattere Punto Esclamativo davanti. Così facendo, qualora non ci si trovi nella finestra corretta, sarà eseguita l’istruzione alternativa, interrompendo il flusso dello script subito dopo. In questo modo, si può concludere immediatamente anche la prima struttura di controllo, senza racchiudere tutto il codice dentro ad un’unica struttura principale. Tale tipo di soluzione, così come già detto, è quella di solito adottata dai programmatori di Jaws, e di cui in ogni caso ci serviremo d’ora in poi, soprattutto nel caso dei controlli sulle finestre.

Codice.


Script MuoveElementoSuccessivo ()
If !SiamoNellaFinestra (MANAGER) Then; se non si è nella finestra corretta,
PronunciaEsegue (CONTROL_FRECCIAGIU); attiva lo script di Jaws con i tasti indicati,
Return; e interrompe il flusso
EndIf; fine controllo finestra
TypeKey (F2); richiama il comando originale
Refresh (); resetta la schermata
SayLine (); legge la riga corrente
EndScript

Collaudo.

  1. Salvate compilando e poi, da dentro all’Editor, eseguite lo script tramite la combinazione
    Windows+FrecciaGiù
    . Il cursore dovrebbe portarsi sull’intestazione dello script successivo.
  2. Provate ora ad aprire il blocco note, o Wordpad, con un documento aperto non vuoto. Eseguendo lo script, ci si porterà sul paragrafo successivo, il quale dovrebbe essere anche letto da Jaws.

Esercizio 7.5.4. La nuova versione di MuoveElementoPrecedente ().

FileScript.

Default.JSS

Nome.

MuoveElementoPrecedente

Descrizione.

Utilizzare la funzione nativa dell’Editor di Script per portarsi all’elemento di codice precedente, purché ci si trovi nell’Editor stesso. In tutti gli altri applicativi, viene eseguito lo script originale di Jaws abbinato alla combinazione di tasti per lo spostamento al paragrafo precedente.

Novità.
  1. Le costanti
    CONTROL_FRECCIASU
    e
    SHIFT_F2
    , che corrispondono ai tasti per simulare, nell’ordine, l’esecuzione dello script per il passaggio al precedente paragrafo, e il comando dell’Editor con lo spostamento all’elemento precedente.
Note.

Il tipo di modifica da compiere, rispetto alla forma originaria dello script, è la stessa esaminata nell’esercizio appena aggiornato. Le differenze stanno ovviamente nel codice, dove, nell’ordine:

  1. La costante con la combinazione tasti che attiva il passaggio al paragrafo precedente, da porre come parametro alla funzione
    PronunciaEsegue ()
    , è in questo caso
    CONTROL_FRECCIASU.
  2. La costante con il comando per il passaggio all’elemento precedente, da porre invece quale parametro alla funzione
    TypeKey ()
    , è stavolta
    SHIFT_F2.

Codice.


Script MuoveElementoPrecedente ()
If !SiamoNellaFinestra (MANAGER) Then; se non si è nella finestra corretta,
PronunciaEsegue (CONTROL_FRECCIASU); attiva lo script di Jaws con i tasti indicati,
Return; ed interrompe il flusso
EndIf; fine controllo finestra
TypeKey (SHIFT_F2); richiama il comando originale
Refresh (); resetta la schermata
SayLine (); legge la riga corrente
EndScript

Collaudo.

Una volta salvato il lavoro, ripetete il collaudo eseguito per lo script precedente, cambiando ovviamente il tasto da premere in
Windows+FrecciaSu.

***

Riepilogo.

Una notevole produzione di codice ha contraddistinto questo capitolo. Il grande sforzo è però stato ricompensato, in quanto abbiamo affrontato uno dei temi più importanti, e speriamo ora meno ostici, dell’intera gestione di Jaws: l’uso delle Finestre.

Probabilmente non siamo ancora riusciti a rendere bene l’idea dell’importanza di questo passaggio, ma il codice che produrremo d’ora in poi prevede uno sfruttamento pressoché sistematico dei controlli messi a punto in queste ultime pagine.

Nel prossimo capitolo chiuderemo il cerchio sui tipi di funzione, analizzando le
Funzioni Evento
. Grazie a questi elementi di codice, realizzeremo il ritorno ad una determinata posizione all’ingresso in un file, o dopo una sostituzione di testo.

Proseguiremo poi con un breve accenno sugli oggetti, limitandoci a dare le informazioni che potrebbero essere utili nei tipi di script sin qui realizzati. Dopo aver spiegato quali siano i file fondamentali per Jaws, e come si possano utilizzare dei file compilati JSB nei nostri sorgenti testuali, chiuderemo il capitolo con una procedura per creare un aiuto in linea automatico.

Download

File script da scaricare, per gli utenti di Jaws fino alla versione 18
Archivio da scaricare, per gli utenti dalla versione 2018 in poi

Per ulteriori spiegazioni, scrivere a:

Abramo Volpato

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *