Logo dell'UIC Logo TUV

Unione Italiana dei Ciechi e degli Ipovedenti ETS - APS

 

Uiciechi.it

torna alla visualizzazione del numero 09 del Uiciechi.it

Numero 09 del 2021

Titolo: Gli script di Jaws 13a. Le procedure guidate: controllo dei dati e funzioni hook.

Autore: Abramo Volpato.


Articolo:
Gli script di Jaws 13a. Le procedure guidate: controllo dei dati e funzioni hook.

Di Abramo Volpato.

13.1. Realizzare un'applicazione con gli script.

Dopo aver fatto tanta strada nel nostro viaggio, eccoci dunque arrivati all'ultimo argomento tra quelli trattati. In realtà, malgrado si tratti del rettilineo finale, la sua lunghezza consiglia di spezzarlo comunque in due parti, assegnando al capitolo che inizia un ruolo soltanto preparatorio.

Anche questo tema, per quanto complesso, ruota attorno ad un solo elemento di codice principale, che ci consente di far funzionare poi tutto quello che ci serve per raggiungere l'obiettivo. Nonostante tale elemento vada realizzato solo nel prossimo ed ultimo capitolo, è necessario chiarire fin d'ora che il nostro obiettivo è allestire una serie di procedure guidate, con le quali riusciremo in particolare a:

1. Sfruttare le tre funzionalità mancanti di "MuoveDato ()", potendo inoltre inserire e modificare le varie stringhe da utilizzare come elementi di ricerca, ed in più facendolo da dentro i tipi di documento a cui esse andranno applicate.

2. Registrare e gestire le Macro testuali, sempre dai documenti dove andranno inserite.

3. Scrivere, modificare, cancellare o duplicare gli script a gestione personale, direttamente da dentro gli applicativi in cui agiranno.

Così com'è successo lo scorso capitolo, sezioneremo la trattazione sulla base dei blocchi di elementi collegati tra essi, e che ruotano attorno ad una delle funzioni chiamate dal citato elemento principale. L'unica eccezione in tal senso sarà rappresentata dal modo in cui Jaws consente di cambiare la risposta ai tasti premuti, come avviene ad esempio nella modalità "Aiuto tastiera", che illustreremo con più titoli e con degli elementi di codice per fare una prova pratica.

A parte le presentazioni dei singoli blocchi, ci fermeremo comunque di tanto in tanto per proporre delle brevi pillole di approfondimento di alcuni temi. Il collaudo del nostro lavoro, tuttavia, non potrà che essere rinviato all'ultimo capitolo.

Ed ora, per la penultima volta, il solito inizio dedicato ai nostri file personali.

Esercizio 13.1.1. Aggiornare il file Personale delle Costanti.

TUTTI = 2, ; valore per indicare l'aggiornamento di tutti i file tasti degli script a gestione personale
CANCELLA = 1, ; valore positivo per chiedere la cancellazione di un elemento
TASTI_HOOK = "TastiHook", ; funzione per predisporre la cattura dei tasti
FRECCIA_DESTRA = "RightArrow", ; versione inglese dell'omonimo tasto
FRECCIA_SINISTRA = "LeftArrow", ; versione inglese dell'omonimo tasto
GESTIONE = 3, ; indica gli script a gestione personale
NATIVO = 1, ; indica gli script nativi di Jaws
ERRORE2 = "DoDoop9", ; suono per errore in basso
INSERT_T = "Insert+T", ; combinazione tasti omonima
JAWSKEY_T = "JAWSKey+T", ; combinazione tasti omonima
PRE_PROCESS_KEY = "InterrompeAttesa (strKeyName); chiama l'apposita funzione",
MAX_PULSANTI = 5, ; numero massimo dei pulsanti nelle procedure guidate
ATTIVA_SINTESI = "AttivaSintesi", ; funzione omologa
SU = "su", ; termine omonimo

Esercizio 13.1.2. Aggiornare il file Personale delle Variabili Globali.

Int gnAggiorna, ; valore per la conclusione di un ciclo
Int gnConta, ; contatore temporaneo
Int gnEcoTastiera, ; valore corrente dell'omonima impostazione
Int gnLivello, ; ultimo livello elaborato in una procedura guidata
Int gnNuovoScript, ; indicatore di uno script di cui controllare la presenza nell'archivio personale
Int gnScriveTasto, ; attiva la trascrizione dei tasti premuti dentro a PreProcessKeyPressedEvent ()
int gnTasto, ; valore assunto dai tasti opzionali
int gnVoce, ; puntatore della voce selezionata
String gsAmbito, ; contesto in cui uno script a gestione personale deve agire
String gsAvviso, ; messaggio da leggere in modo differito
string gsChiama, ; prima parte del nome della funzione da chiamare alla conclusione della procedura
String gsInfo, ; informazioni nei campi di elaborazione testo.
String gsMassimi, ; elenco di valori massimi
String gsMinimi, ; elenco di valori minimi
String gsNuoviTasti, ; elenco dei tasti modificati durante la sessione
String gsSezione, ; il nome della sezione in cui operare
String gsSuffisso, ; ultimo suffisso specificato come parametro
String gsTastiScript, ; tasti di attivazione di uno script
String gsVoce, ; memorizza la voce corrente in un elenco
String gsRimuoviTasti, ; combinazione tasti di cui rimuovere l'assegnazione nel file tasti corrente
Int gnCambiati, ; indicatore della presenza di dati modificati nel record corrente

Esercizio 13.1.3. Aggiornare il file Personale dei Messaggi.

; Nessun file configurazione del tipo specificato
@msgNoFileCampi
File configurazione per la categoria %1 non trovato. Crearlo ora?
@@
; Nessuna fase valida presente nel file configurazione
@msgNoCampiValidi
Dati sui campi non presenti, o non validi, nel file %1.JCF. Crearli ora?
@@
; invita a specificare i tasti di attivazione negli script a gestione personale
@msgAttivazione
Premere i tasti di attivazione dello script %1. Invio conferma, Esc annulla.
@@
; elenco prefissi direzionali per i tasti di attivazione
@lstPrefissiTasti
Left|Right
@@
; titolo per conferma alla sovrascrittura dei tasti di attivazione
@ttlTastiUtilizzati
I tasti premuti sono già utilizzati da uno script %1, %2.
@@
; elenco con i tipi di script
@lstTipiScript
nativo|dell'Utente|a gestione personale
@@
; mancata immissione di tasti per l'attivazione degli script a gestione personale
@ttlNoPremuti
Nessun tasto di attivazione indicato.
@@
; conferma al ritorno ad una fase d'inserimento
@msgTornaImmissione
Volete tornare all'inserimento?
@@
; conferma dell'abbandono di una fase d'inserimento
@ttlAbbandono
Confermate l'abbandono dell'inserimento?
@@
; avviso di modificare i tasti di attivazione script impostati
@msgCambiaTasti
Modificare i tasti premuti, o cambiare prima quelli dello script esistente.
@@
; messaggio per conferma alla sovrascrittura dei tasti di attivazione
@msgTastiUtilizzati
Continuando, si sovrascriverà l'impostazione esistente.
@@
; esito con registrazione effettuata
@msgOkTasti
Tasti memorizzati.
@@
; base per etichetta dei campi
@msgCampo
Campo%1
@@
; suffisso per le sezioni
@msgSezioni
nella sezione %1 dell'archivio %2.
@@
; base per nome delle chiavi con i dati sui pulsanti
@msgPulsante
Pulsante%1
@@
; base per aggiunta con il carattere Pipe
@msgPipe
|%1
@@
; base per un prefisso numerico
@msgNumerico
%1. %9
@@
; base per tre termini separati dal carattere Pipe
@msg3Pipe
%1|%2|%3
@@
; elenco delle opzioni impostabili come ambiti negli script personali
@lstAmbitiScript
Chiude|Esce|Salva|Tabella
@@
; virgola, e spazio successivo, aggiunti ad un termine
@msgVirgola
%1, %9
@@
; dati incompleti nei record
@ttlDatiMancanti
%1 record, %2con dati incompleti.
@@
; consenso alla rimozione dei record non validi
@msgRimozioneDati
Continuando, tali record saranno rimossi.
@@
; esito record cancellati
@hlpRimuoviRecord
%1 record rimoss%2.
@@
; errore nel trattamento dei record
@hlpErroreRecord
Impossibile %1re %2 record %3 %4.
@@

13.2. Dati preliminari.

Questo primo blocco di cinque funzioni è dedicato, come dice il titolo, ad impostare e controllare i dati preliminari. Per poter capire cosa siano questi dati, e quale sia il motivo di tale controllo, è però necessario spiegare in breve come funziona la procedura che stiamo allestendo.

Tra gli aspetti fin qui esaminati di Jaws, ciò che più si avvicina a quello che andremo a fare è la procedura guidata di creazione degli script. In altre parole, tramite un comando, noi entreremo in un ambiente nel quale potremo aggiungere,modificare o cancellare dei dati, i quali potranno essere a loro volta composti da:

1. un solo campo, con un elenco di voci che potranno essere selezionate usando le frecce in su ed in giù, e che potranno essere modificate, aggiunte o eliminate, sempre e solo da questo elenco.

2. Una serie di campi, dove ogni singola voce potrà essere come prima selezionata, modificata, aggiunta o eliminata, ma alla quale saranno collegati altri campi di un record, i quali potranno essere a loro volta elaborati, ciascuno in una propria e diversa schermata della stessa procedura.

Facendo un esempio con quel poco che già conosciamo, al primo tipo di procedura appartiene la ricerca di stringhe predeterminate, che abbiamo chiamato anche elementi di ricerca, dove all'ingresso nella procedura potremo inserirne un numero da uno a nove. Tali elementi, come detto, potranno essere così modificati o cancellati, aggiungendone poi fino al numero massimo impostato.

All'altro tipo di procedura appartengono invece gli script a gestione personale, che invece abbiamo stabilito che possano essere fino ad un massimo di 99. In questo caso, nella prima schermata l'elenco di voci sarà il nome da assegnare a tali script, mentre aprendo schermate successive, si potranno aggiungere o modificare i dati relativi ad altri campi, come i tasti di attivazione, il testo del sommario, o i comandi che ciascun script deve eseguire.

L'elemento comune a queste due tipologie di procedura è, come detto, la schermata principale, a cui anche negli script bisognerà tornare per effettuare le modifiche sostanziali, come l'aggiunta o la cancellazione. Pur partendo dunque da alcune basi comuni, il fatto di poter elaborare questa o quella tipologia di procedura dipende da alcuni dati, da noi predisposti fin dal capitolo scorso in alcuni file di configurazione in formato "INI".

L'unico problema dei dati registrati in questi archivi testuali è che ciascun utente può, almeno in teoria, modificare tali archivi anche manualmente. Se tale opportunità è comunque utile, è pur sempre possibile modificare in modo errato tali file, qualora li si abbia per qualche motivo da aprire, casomai togliendo eventuali dati indispensabili al funzionamento delle singole procedure.

Per questo motivo, in particolare una delle prime funzioni che andremo a realizzare nel prossimo blocco si occupa proprio di controllare il contenuto dei file di configurazione, quelli che lo scorso capitolo abbiamo previsto di creare tramite un apposito elemento di codice. Se le sezioni indispensabili dell'archivio sono presenti, a prescindere dall'ordine in cui si trovino, allora il flusso della procedura prosegue, altrimenti viene fermato.

Anche se l'elemento chiamato dalla funzione principale è l'ultimo del blocco, la funzione più complessa è però quella che controlla l'eventuale corretta presenza di tasti di attivazione negli script, in particolare di quelli a gestione personale. Tale funzione, lunga un centinaio di righe, controlla gli abbinamenti tra tasti e script, verificando che essi siano corretti, e casomai cancellandoli, qualora lo script abbinato non esista.

La funzione, in queste fasi iniziali, serve ad evitare che siano elaborati dei dati inesatti. Questo stesso elemento, in ogni caso, sarà chiamato anche alla fine della procedura, per aggiornare i file tasti con le eventuali modifiche apportate alle impostazioni registrate.

Esercizio 13.2.1. La funzione ResettaCampi.

FileScript. Default.JSS

Nome. ResettaCampi

Descrizione. Azzera valori e dati delle procedure guidate.

Ritorni. Di tipo Void. Nessuno.

Note.

1. Questa funzione viene chiamata sia all'inizio, per non causare effetti indesiderati durante le impostazioni, sia alla fine del lavoro, per lasciare la memoria pulita, e consentire l'utilizzo di tali variabili per altri script o procedure.

2. La funzione, se non altro, pone direttamente nel codice un elenco pressoché completo delle variabili globali utilizzate in questa procedura, senza doverle estrapolare dal file personale che le include assieme a tutte le altre.

Codice.

Void Function ResettaCampi ()
; annulla il contenuto delle variabili globali per:
Let gnAggiorna = FALSE; indicatore d'uscita dal ciclo interno
Let gnCampo = FALSE; campo di elaborazione
Let gnConferma = FALSE; conferme all'uscita
Let gnConta = FALSE; contatore delle chiavi temporanee
Let gnEcoTastiera = FALSE; valore corrente dell'omonima impostazione
Let gnFerma = FALSE; indicatore del tipo d'interruzione
Let gnLivello = FALSE; ultimo campo trattato
Let gnMaxCampi = FALSE; numero complessivo dei campi
Let gnMaxVoci = FALSE; numero delle voci possibili
Let gnMultiple = FALSE; inserimento su più righe
Let gnNumerico = FALSE; prefisso numerico alle voci di scelta
Let gnNuovoScript = FALSE; indicatore di un nuovo script
Let gnProgrammato = FALSE; identificativo di un avvio programmato
Let gnSalta = FALSE; indicatore di salto dei controlli
Let gnScriveTasto = FALSE; trascrizione dei tasti premuti
Let gnStato = FALSE; stato di attivazione della sintesi vocale
Let gnTasto = FALSE; numero del tasto opzionale
Let gnTipo = FALSE; tipologia di procedura
Let gnTotali = FALSE; voci complessive registrate
Let gnValore = FALSE; valore temporaneo
Let gnVoce = FALSE; valore della voce attiva
Let gsAmbito = NULLO; ultimo ambito registrato
Let gsArchivio = NULLO; nome del file di configurazione
Let gsAttiva = NULLO; chiave della voce attiva
Let gsAvviso = NULLO; informazioni dalla procedura
Let gsCategoria = NULLO; tipologia di procedura
Let gsChiama = NULLO; prefisso della funzione chiamata a fine procedura
Let gsChiave = NULLO; chiave attiva del record
Let gsElenco = NULLO; chiavi valide del record
Let gsEtichette = NULLO; elenco dei pulsanti validi
Let gsInfo = NULLO; testo per i messaggi della procedura
Let gsMassimi = NULLO; elenco dei valori massimi per una voce
Let gsMinimi = NULLO; elenco dei possibili valori minimi
Let gsNuoviTasti = NULLO; chiavi dei record con Tasti di attivazione modificati
Let gsOggetto = NULLO; soggetto dell'azione da compiere

Let gsSezione = NULLO; sezione dell'archivio in cui operare
Let gsSuffisso = NULLO; estensione o nome file del documento corrente
Let gsTastiScript = NULLO; Tasti di attivazione dello script
Let gsTermine = NULLO; termine da formattare nei messaggi
Let gsTitolo = NULLO; titolo per la finestra di dialogo
Let gsVoce = NULLO; contenuto della voce attiva
EndFunction

Collaudo.

1. Anche in questo capitolo, sino alla fine non si potrà che compilare dopo ogni elemento realizzato, e casomai rendere opzionali dei parametri quando ciò venga richiesto.

Esercizio 13.2.2. La funzione PronunciaUscita .

FileScript. Default.JSS

Nome. PronunciaUscita

Descrizione. Concentra in un'unica funzione una serie di comandi per la chiusura dell'elaborazione, compresa la lettura della riga corrente.

Ritorni. Di tipo Void. Nessuno.

Novità.

1. La nostra funzione "ResettaCampi ()".

Note.

1. Questa è una delle prime funzioni chiamate dalla procedura principale, e contiene solo una serie di istruzioni che sono necessarie nei vari punti dai quali si può uscire dalla procedura stessa, tra le quali anche la chiamata alla citata funzione "ResettaCampi ()".

2. L'unica breve struttura di controllo presente si occupa di attivare la funzione solo quando fosse spenta, poiché la riattiverebbe con specificato il valore per la cancellazione del buffer. Per questo, il controllo deve intervenire solo quando serve, poiché in tutte le altre occasioni rischierebbe di impedire la pronuncia di messaggi precedenti alla chiamata della stessa funzione.

Codice.

Void Function PronunciaUscita ()
suona (ULTIMO_SEGNO); emette un arpeggio discendente
If IsSpeechOff () Then; se la sintesi è spenta,
SpeechOn (TRUE); la riattiva
EndIf; fine controllo stato sintesi
ResettaCampi (); ripulisce la memoria dalle impostazioni,
Refresh (); resetta anche la schermata,
SayLine (); e pronuncia il contenuto della riga corrente
EndFunction

Esercizio 13.2.3. La funzione RilevaCampi.

FileScript. Default.JSS

Nome. RilevaCampi

Descrizione. Cerca nell'archivio di configurazione le etichette di sezione, valide per la configurazione dei campi nelle procedure guidate.

Ritorni. Di tipo Int. TRUE, per etichette di campi trovate; FALSE, per nessuna etichetta valida.

Fasi.

1. Il codice è compreso tutto all'interno di un ciclo "While", che si ripete finché non viene trovata almeno un'etichetta valida.

2. Entrati nel ciclo, si rilevano dapprima le sezioni presenti nel file configurazione della categoria impostata nella relativa variabile globale; se tali sezioni esistono, tramite un ciclo "For" le si scorrono, verificandone il nome.

3. Se il nome di una sezione non è valido, il ciclo viene subito interrotto; se invece è regolare, essa viene aggiunta alla variabile che fa uscire dal ciclo principale.

4. Se all'uscita dal ciclo di analisi delle sezioni, tali elementi risultano assenti o non validi, viene consentito di creare o aggiornare il file di configurazione; se questa scelta viene confermata, si azzera l'elenco delle sezioni e si ritorna all'inizio del ciclo generale; se invece si annulla la creazione dei file, il flusso viene interrotto.

5. Se invece tutti i controlli sono regolari, il ciclo generale viene interrotto restituendo l'esito positivo.

Note.

1. Come accennato nella premessa, la funzione si occupa di eseguire un primo sommario controllo sui contenuti del file di configurazione per la categoria di procedura scelta, in particolare controllandone il numero e la correttezza delle sezioni di dati inserite; in altre parole, mentre la nostra funzione dello scorso capitolo, "ArchivioDati ()",creava un nuovo file solo se esso non esisteva, qui si dà la possibilità di ricrearne una versione corretta, qualora vi siano stati rilevati degli errori.

Codice.

Int Function RilevaCampi ()
Var
String sSezioni, ; elenco delle sezioni rilevate
Int iSezioni, ; numero delle sezioni
Int i, ; contatore del ciclo
String sSezione, ; singola sezione estratta
String sSuffisso, ; suffisso numerico in forma testuale
String sTesto, ; prima parte del nome di sezione
Int iValore, ; variabile temporanea
Int iMassimo, ; valore massimo di un campo valido rilevato
String sNumeri, ; elenco dei valori abbinati alle etichette dei campi
String sMessaggio; eventuale avviso per errore nei dati dei campi

While !sNumeri; continua finché l'elenco dei campi rimane vuoto
Let sSezioni = SezioniUtente (gsCategoria); memorizza tutte le sezioni presenti
Let iSezioni = StringSegmentCount (sSezioni, PIPE); conta le sezioni rilevate
For i = 1 To iSezioni; scorre le sezioni nell'archivio
Let sSezione = StringSegment (sSezioni, PIPE, i); estrae la singola sezione
If sSezione != ELABORA Then; se i dati non sono per le impostazioni della singola procedura,
; estrae un eventuale suffisso numerico dalla stringa
Let sSuffisso = EstraeNumero (sTesto, sSezione)
Let iValore = StringToInt (sSuffisso); prova a convertire in numero il suffisso testuale
If sTesto != CAMPO ; se la prima parte della sezione e del prefisso standard sono diverse,
|| !iValore Then; oppure, il suffisso numerico non è un numero valido,
Let i = iSezioni + 1; cambia il contatore, per l'uscita immediata dal ciclo
Else; altrimenti, se il controllo è regolare,
Let sNumeri = CambiaCampo (sNumeri, sSuffisso, ULTIMA); ne aggiunge il dato in coda
If iValore > iMassimo Then; se il suffisso ha un valore maggiore tra quelli rilevati,
Let iMassimo = iValore; aggiorna la variabile
EndIf; fine controllo valore massimo
EndIf; fine controllo ripetizioni
EndIf; fine controllo sezione
EndFor; fine scansione sezioni
Let gnMaxCampi = StringSegmentCount (sNumeri, PIPE); conta i campi validi rilevati
If !gnMaxCampi ; se nessuna sezione è stata trovata,
|| iMassimo != gnMaxCampi Then; oppure, se il numero massimo rilevato non è il totale dei campi,
If !gnMaxCampi && !sSezioni Then; se, oltre ai campi, manca pure il file configurazione,
Let sMessaggio = msgNoFileCampi; imposta la base per segnalarne l'assenza
Else; altrimenti, se non vi sono campi validi, o non in numero sufficiente,
Let sMessaggio = msgNoCampiValidi; imposta la relativa base
EndIf; fine controllo tipo errore
; se si conferma di avviarne la creazione,
If ChiedeConferma (FormatString (sMessaggio, gsCategoria)) Then
; cancella l'eventuale versione esistente del file,
DeleteFile (FormatString (msg2Controbarra, GetUserSettingsDirectory (), gsCategoria + JCF))
Let sNumeri = NULLO; e resetta il dato per riavviare il ciclo di inserimento
If !ConfigurazioneCampi () Then; se i campi non sono stati impostati,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo impostazione campi
Else; altrimenti, se non si conferma la configurazione dei campi,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo conferma
Else; altrimenti, se tutti i controlli sono regolari,
Return TRUE; restituisce l'esito positivo
EndIf; fine controllo esito
EndWhile; fine del ciclo principale
EndFunction

***

Per ulteriori spiegazioni, scrivere a:

Abramo Volpato, oppure a: Nunziante Esposito



Torna alla pagina iniziale della consultazione delle riviste

Oppure effettua una ricerca per:


Scelta Rapida