Logo dell'UIC Logo TUV

Unione Italiana dei Ciechi e degli Ipovedenti ETS - APS

 

Uiciechi.it

torna alla visualizzazione del numero 10 del Uiciechi.it

Numero 10 del 2021

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

Autore: Abramo Volpato.


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

Di Abramo Volpato.

Note.

1. Nella prima struttura che intercetta i tasti premuti, nel caso di Invio ed Escape, il controllo viene effettuato confrontando sia i tasti di attivazione legati allo script rilevato dalla funzione hook, sia quelli che sono stati registrati da noi tramite la funzione "PreProcessKeyPressedEvent ()"; in quest'ultimo caso, è proprio la funzione evento che, come analizzeremo più avanti, chiama la funzione hook simulando la sua attivazione; quest'ultima, invece, può avvenire in modo automatico solo nel caso in cui ai citati tasti siano già abbinati degli script.

2. Il rientro alla funzione principale della procedura, che è in pratica l'ultima istruzione del codice, viene eseguita tramite la chiamata della funzione "CallFunctionByName ()", poiché tale funzione principale dobbiamo ancora realizzarla; con questo stratagemma, infatti, evitiamo qualsiasi problema in fase di compilazione della funzione che stiamo illustrando.

Codice.

Void Function TastiHook (string sNomeScript)
Var
String sTasti, ; ultimi tasti premuti
String sTitolo, ; titolo per la schermata di scelta
Int iTipo, ; tipo di script rilevato
Int iOpzioni, ; scelte possibili nella finestra di dialogo
String sMessaggio, ; testo per il corpo della schermata di scelta
String sPrecedente; eventuale dato preesistente

Let gnFerma = FALSE; annulla l'eventuale valore impostato per attivare la funzione
Let sTasti = LeggeDato (TEMPORANEO, TASTI, IntToString (gnConta)); rileva gli ultimi tasti premuti
If GetScriptKeyName (sNomeScript) == INVIO ; se si è attivato uno script con Invio,
|| sTasti == INVIO Then; oppure, il tasto Invio è stato comunque premuto,
If !sTasti Then; se è presente solo un nome di script,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo presenza tasti
FermaHook (); disattiva l'hook
If gnConta If ChiedeConferma (ttlNoPremuti, msgTornaImmissione) Then; se si è deciso di riprovare l'immissione,
AvviaHook (); riavvia la funzione,
Return FALSE; e interrompe il flusso
Else; altrimenti, se si abbandona l'immissione,
suona (ERRORE2); emette un segnale acustico,
Let sTasti = NULLO; e resetta il dato
EndIf; fine controllo scelta
Else; altrimenti, se la conclusione è regolare,
Let sTasti = LeggeDato (TEMPORANEO, TASTI, IntToString (gnConta - 1))
EndIf; fine controllo pressione tasti
ElIf GetScriptKeyName (sNomeScript) == ESC ; se invece si è attivato uno script con Esc,
|| sTasti == ESC Then; oppure, il tasto Esc è stato comunque premuto,
If !sTasti Then; se è presente solo un nome di script,
Return FALSE; restituisce un risultato nullo
EndIf; fine controllo presenza tasti
FermaHook (); disattiva l'hook
If !ChiedeConferma (ttlAbbandono, NULLO, FALSE, SECONDA) Then; se si si riprova l'immissione,
AvviaHook (); riavvia la funzione,
Return FALSE; e interrompe il flusso
Else; altrimenti, se si abbandona l'immissione,
suona (ERRORE2); emette un segnale acustico,
Let sTasti = NULLO; e resetta il dato
EndIf; fine controllo scelta
ElIf sTasti == INSERT_T ; se si sono premuti i tasti per la lettura del titolo,
|| sTasti == JAWSKEY_T Then; oppure, si sono premuti gli altri tasti per lo script,
SayFormattedMessage (OT_HELP, msgAttivazione, NULLO, gsAttiva); legge il titolo,
CancellaChiave (TEMPORANEO, TASTI, IntToString (gnConta)); rimuove la registrazione dei tasti,
Let gnConta = gnConta - 1; toglie un'unità al contatore,
Return FALSE; E interrompe il flusso
Else; altrimenti, alla pressione di tasti abbinati ad un qualsiasi altro script,
FermaHook (); disattiva temporaneamente l'hook
; formatta il titolo della schermata controllandone l'origine
Let sTitolo = OrigineScript (sNomeScript, iTipo)
If iTipo == GESTIONE Then; se si tratta di uno script a gestione personale,
Let iOpzioni = OK; imposta di proporre una sola conferma senza scelta
Let sMessaggio = msgCambiaTasti; e imposta anche il messaggio invitando a modificare i tasti
Else; altrimenti, in tutti gli altri casi,
Let iOpzioni = FALSE; lascia le scelte predefinite, con Ok e Annulla,
Let sMessaggio = msgTastiUtilizzati; e imposta l'avviso di sovrascrittura
EndIf; fine controllo tipo script
; propone una finestra di scelta dove confermare la sovrascrittura dei tasti già presenti
If !ChiedeConferma (sTitolo, sMessaggio, iOpzioni, SECONDA) ; se non la si conferma,
|| iTipo == GESTIONE Then; o i tasti premuti appartengono ad uno script a gestione personale,
AvviaHook (); riavvia la funzione,
Return FALSE; e interrompe il flusso
EndIf; fine controllo scelta
EndIf; fine controllo tasti premuti
; registra l'eventuale dato già presente
Let sPrecedente = LeggeCampo (gsArchivio, gsSezione, gsChiave)
If !sTasti Then; se nessun tasto valido è stato rilevato,
If !sPrecedente Then; se nessun tasto è registrato,
Let gnCampo = PRIMA; torna alla schermata iniziale
EndIf; fine controllo tasti registrati
Else; altrimenti, se dei tasti sono stati specificati,
Let gsTastiScript = ConverteTasti (sTasti); converte I TASTI rilevati nella forma valida per i file JKM
; tenta di salvare i tasti definiti nell'archivio di dati
If ScriveCampo (gsArchivio, gsSezione, gsChiave, gsTastiScript) Then; se la scrittura riesce,
SayMessage (OT_ERROR, msgOkTasti); avvisa dell'esito positivo,
Let gnCambiati = TRUE; e attiva il controllo nell'archivio degli script a gestione personale
If !sPrecedente Then; se il dato non esisteva,
Let gnFerma = CATTURA; ripristina il valore, per consentire il passaggio diretto alla schermata successiva
EndIf; fine controllo preesistenza dato
If sTasti != sPrecedente Then; se in ogni caso i tasti sono cambiati,
Let gsNuoviTasti = CambiaCampo (gsNuoviTasti, gsChiave, ULTIMA); aggiunge la chiave corrente
EndIf; fine controllo modifica tasti
Else; altrimenti, in caso di errore,
Let gnCampo = PRIMA; torna alla schermata iniziale
EndIf; fine controllo scrittura
EndIf; fine controllo presenza dato
Let gnSalta = TRUE; consente di rientrare nei cicli senza resettare le impostazioni,
CallFunctionByName (ELABORA + DATO, gsSuffisso, TRUE); e torna alla procedura principale
EndFunction

Collaudo.

1. Dopo aver compilato, ricordiamo di rendere opzionale l'unico parametro della funzione.

Esercizio 13.3.9. La funzione InterrompeAttesa.

FileScript. Default.JSS

Nome. InterrompeAttesa

Descrizione. Controlla l'avvenuta pressione dei tasti che fermano l'attesa dell'immissione di quelli per l'attivazione degli script. Se così è, sono trasmessi dei dati tramite le variabili globali, e viene chiamata la funzione di analisi dei tasti premuti.

Ritorni. Di tipo Void. Nessuno.

Parametri.

1. sTasti. Il nome originale dei tasti premuti, comprese eventuali parti identificative da rimuovere. Di tipo String.

Novità.

1. La prima chiamata della nostra funzione "TastiHook ()", anche se essa avviene non direttamente tramite il codice, bensì grazie alla funzione nativa che consente di porre, come loro primo parametro, i nomi di funzioni da chiamare.

2. La costante testuale "TASTI_HOOK", che contiene il nome esteso della funzione omologa.

Note.

1. Il codice è composto da un'unica struttura di controllo, con due livelli annidati l'uno dentro l'altro, dove il flusso entra solo nel caso che l'attesa dei tasti sia stata attivata tramite un valore impostato nell'apposita variabile globale; se così è, i tasti premuti sono registrati in un apposito archivio temporaneo.

2. Sempre nel caso sia stata attivata l'attesa, se i tasti premuti sono Invio o Escape, sarà chiamata direttamente la funzione che viene coinvolta dalla pressione dei tasti legati agli script, sfruttando l'apposita funzione nativa per indicarla come parametro. Qui l'analisi del codice produrrà o il ritorno alla fase di attesa tasti, oppure l'interruzione di tale attesa, che dovrà essere in ogni caso confermata dall'Utente.

Codice.

Void Function InterrompeAttesa (string sTasti)
If gnScriveTasto Then; se la cattura dei tasti premuti è stata avviata,
Let gnConta = gnConta + 1; aggiorna il contatore delle chiavi,
ScriveDato (TEMPORANEO, TASTI, IntToString (gnConta), sTasti); e vi annota i tasti rilevati
If sTasti== INVIO ; se si è premuto il tasto Invio,
|| sTasti== ESC Then; oppure, se si è premuto il tasto Escape,
CallFunctionByName (TASTI_HOOK); esegue le azioni conseguenti
EndIf; fine controllo tasti
EndIf; fine controllo trascrizione
EndFunction

Esercizio 13.3.10. Lo script MetteMacroTesto5.

FileScript. Default.JSS

Nome. MetteMacroTesto5

Sommario. Inserisce una riga di codice nel documento.

Descrizione. Chiama l'apposita funzione di scrittura testo, per inserire nel documento il contenuto di una costante che corrisponda alla riga di codice da aggiungere.

TastiAttivazione. Shift+Control+5

Novità.

1. La costante "PRE_PROCESS_KEY", la quale contiene l'istruzione che chiama la funzione appena realizzata, "InterrompeAttesa ()".

Note.

1. Così come gli omologhi script del decimo capitolo, questo serve soltanto a compiere senza errori una modifica ad un elemento di codice nativo, anche in questo caso una funzione evento, il cui contenuto sarà aggiornato seguendo quanto riportato nel prossimo elemento.

Codice.

Script MetteMacroTesto5 ()
MetteTesto (PRE_PROCESS_KEY, TRUE); inserisce la riga di codice, andando poi a capo
EndScript

Collaudo.

1. Come nei citati precedenti, limitatevi a compilare, perché il test lo faremo nel prossimo elemento, quando eseguiremo la modifica che si deve apportare al codice.

Esercizio 13.3.11. La versione aggiornata di PreProcessKeyPressedEvent ().

FileScript. Default.JSS

Nome. PreProcessKeyPressedEvent

Novità.

1. La nostra funzione "InterrompeAttesa ()".

Note.

1. La modifica alla versione originale va effettuata individuando la funzione evento all'interno del file script predefinito; non è necessario spostarla in un punto situato dopo le nostre dichiarazioni di inizio codice, in quanto essa chiamerà una nostra funzione senza usare costanti o variabili globali nella sintassi, ma è comunque opportuno farlo anche solo per concentrare il codice da noi manipolato in una sezione apposita del file script predefinito. Se decidete di muovere la funzione, dopo averla spostata, provate subito a compilare una prima volta, per verificare se vi siano problemi con la nuova collocazione.

2. In ogni caso, posizionatevi all'inizio della prima istruzione all'interno del codice, quindi attivate lo script appena creato premendo "Shift+Control+5", e dovrebbe inserirsi l'istruzione contenuta nella costante "PRE_PROCESS_KEY". Al termine di tale modifica, la prima riga della funzione, dopo quella d'intestazione, dovrebbe avere l'aspetto riportato nell'apposita scheda a seguito, dove si è comunque omesso la restante parte del codice originale.

3. A tal proposito, un'ultima annotazione: il nome della variabile che consente di memorizzare i tasti premuti, la quale nel codice proposto si chiama "strKeyName", deve essere necessariamente quello inserito come secondo tra i parametri della funzione; Se nel caso della vostra versione di Jaws tale nome fosse diverso, quest'ultimo dovrebbe essere comunque posto come parametro della funzione "InterrompeAttesa ()".

Codice.

Int Function PreProcessKeyPressedEvent (int nKey, string strKeyName, int nIsBrailleKey, int nIsScriptKey)
InterrompeAttesa (strKeyName); chiama l'apposita funzione per memorizzare i tasti premuti
; spazio per il codice originale
EndFunction

Collaudo.

1. Se provate a compilare, dovrebbe essere tutto a posto. Non abbiate timore per aver modificato una funzione così importante, perché al momento non cambierà nulla rispetto al solito. Essa inizierà a lavorare per noi, infatti, solo nel caso in cui si attivi una speciale variabile globale. Tale variabile, a sua volta, dovrebbe essere impostata solo da una nostra procedura guidata, che non collauderemo prima del prossimo capitolo.

Esercizio 13.3.12. La funzione CatturaDato.

FileScript. Default.JSS

Nome. CatturaDato

Descrizione. Avvia l'attesa delle combinazioni tasti per gli script.

Ritorni. Di tipo Void. Nessuno.

Novità.

1. La funzione integrata "GetJCFOption", (OttieniOpzioniDiJaws), la quale restituisce un valore che rappresenta le opzioni attive di Jaws; tale valore va posto nel suo unico parametro, il quale può essere specificato tramite una delle costanti che abbiamo già analizzato nella funzione "SetJcfOption ()".

Note.

1. Questa funzione rappresenta quello che, nel nostro esempio di applicazione hook, era costituito dallo script di innesco, "ModoAlternativo ()"; essa contiene la serie di istruzioni che vanno eseguite solo al primo avvio della nuova modalità.

2. Per quanto appena detto, le istruzioni contenute dentro alla precedente nostra funzione "AvviaHook ()", sono invece quelle che si devono riattivare ad ogni sospensione temporanea della modalità, e per questo la chiamata di tale funzione risulta l'ultima istruzione nel codice sottostante.

Codice.

Void Function CatturaDato ()
Let gsTastiScript = NULLO; resetta il dato da impostare
Let gnEcoTastiera = GetJCFOption(OPT_TYPING_ECHO);salva le impostazioni dell'echo tastiera
Let gnVoce = PRIMA; reimposta la voce corrente sull'unica possibile
Let gnLivello = SECONDA; aggiorna il livello corrente del campo
SpeechOn (TRUE); riattiva comunque la sintesi
AvviaHook (); chiama la funzione per avviare l'hook di cattura tasti
EndFunction

13.4. Acquisizione e controllo dati .

Dopo aver trattato a parte il blocco riguardante le funzioni hook, rimangono solo altri due elementi che si occupano di completare le impostazioni preliminari, in questo caso di quelle per i singoli campi della procedura. In particolare la seconda funzione sarà quella che viene chiamata direttamente dalla funzione principale, e per questo in essa sono chiamate a confluire le altre funzioni collaterali.

Esercizio 13.4.1. La funzione DatiSchermata.

FileScript. Default.JSS

Nome. DatiSchermata

Descrizione. Rileva e trasmette i dati necessari alle selezioni nella procedura guidata.

Ritorni. Di tipo Int. TRUE, per i dati recuperati; FALSE, per nessun dato.

Novità.

1. La nostra funzione "PronunciaUscita ()".

2. La costante "MAX_PULSANTI", che equivale di norma al valore 5, e che corrisponde appunto al numero massimo dei pulsanti impostabili.

Fasi.

1. Dopo un tentativo di lettura dati, una prima struttura di controllo verifica che tali dati ci siano, altrimenti si chiama la nostra funzione Fasi.PronunciaUscita ()", per eseguire le istruzioni preliminari all'abbandono, prima di interrompere il flusso ed uscire così dalla procedura.

2. Una seconda struttura definisce il titolo della schermata, sempre sulla base della categoria di procedura attivata.

3. Dopo aver resettato dei valori iniziali, un ciclo scorre l'archivio cercando i dati dei possibili pulsanti, impostando casomai per ciascuno il limite minimo e massimo necessari per renderlo attivabile.

4. Nell'ultima parte della funzione, sono letti dall'archivio, ed impostati in variabili globali, una serie di dati relativi alla schermata da elaborare, al termine dei quali viene restituito un valore positivo per far proseguire il flusso.

Note.

1. Questa funzione, così come spesso accaduto nel capitolo, è un altro pezzo di codice della funzione generale, spostata in un elemento autonomo per semplificarne l'analisi e le eventuali modifiche.

Codice.

Int Function DatiSchermata ()
Var
String sSezione, ;sezione dell'archivio della procedura
Int i, ; contatore del ciclo
String sDati, ; dati rilevati
Int iPrimo, ; indicatore del primo pulsante
String sDato; variabile temporanea

; compone il nome della sezione di cui leggere dall'archivio della procedura
Let sSezione = FormatString (msgCampo, gnCampo)
If !ChiaviUtente (gsCategoria, sSezione) Then; se nessun dato è stato trovato,
; formatta e pronuncia l'avviso,
SayFormattedMessage (OT_ERROR, hlpNoDato, hlpNoDato_corto, FormatString (msgSezioni, sSezione, gsCategoria))
PronunciaUscita (); esegue delle operazioni di chiusura, leggendo la riga corrente,
Return FALSE; e interrompe il flusso, restituendo un risultato nullo
EndIf; fine controllo dati
Let gnTipo = LeggeNumerico (gsCategoria, ELABORA, TIPO); rileva il tipo di procedura impostato
Let sDati = LeggeRecord (gsCategoria, sSezione, TITOLO); rileva l'eventuale titolo memorizzato
If gnTipo == TERZA Then; se si sta operando su più campi,
Let gsTermine = StringSegment (sDati, SPACE, TERZA); estrae la terza parola del titolo
Else; altrimenti, se si è nei primi due tipi di procedura,
; lo prende formattando categoria e oggetto della procedura
Let gsTermine = FormatString (msg2, gsCategoria, gsOggetto)
EndIf; fine controllo termine da formattare
If sDati Then; se un titolo è stato rilevato,
If gnCampo == PRIMA Then; se si è nella schermata iniziale,
Let gsTitolo = FormatString (sDati, gsTermine); personalizza il titolo con l'apposito termine
Else; altrimenti, nei campi dal secondo in poi,
; personalizza il titolo con la voce della schermata iniziale
Let gsTitolo = FormatString (sDati, gsAttiva)
EndIf; fine controllo campi
Else; altrimenti, se il titolo non c'è,
Let gsTitolo = FormatString (ttlSelezione); imposta un titolo generico
EndIf; fine controllo titolo
; resetta i dati per:
Let gsEtichette = NULLO; etichette dei pulsanti
Let gsMinimi = NULLO; valori minimi per attivare un pulsante
Let gsMassimi = NULLO; valori massimi per attivare un pulsante
For i = 1 To MAX_PULSANTI; scorre i possibili dati
; tenta di rilevare le impostazioni
Let sDati = LeggeRecord (gsCategoria, sSezione, FormatString (msgPulsante, i))
If sDati Then; se dei dati sono stati rilevati,
Let sDato = StringSegment (sDati, PIPE, SECONDA); rileva il valore minimo valido per la voce
If !sDato Then; se nessun dato è stato rilevato,
Let sDato = UNO; imposta il valore predefinito in forma testuale
EndIf; fine controllo valore minimo
If !iPrimo Then; se si è al primo passaggio, inizializza gli elenchi per:
Let gsEtichette = StringSegment (sDati, PIPE, PRIMA); etichette dei pulsanti
Let gsMinimi = sDato; valore minimo per attivare il pulsante
Let gsMassimi = StringSegment (sDati, PIPE, TERZA); valore massimo per attivare il pulsante
Let iPrimo = TRUE; valorizza l'indicatore
Else; altrimenti, aggiunge il risultato ai rispettivi elenchi
Let gsEtichette = gsEtichette + FormatString (msgPipe, StringSegment (sDati, PIPE, PRIMA))
Let gsMinimi = gsMinimi + FormatString (msgPipe, sDato)
Let gsMassimi = gsMassimi + FormatString (msgPipe, StringSegment (sDati, PIPE, TERZA))
EndIf; fine controllo passaggi
EndIf; fine controllo dati
EndFor; fine scansione dati pulsanti
; rileva i dati relativi a:
; un prefisso numerico davanti alle voci
Let gnNumerico = LeggeNumerico (gsCategoria, sSezione, NUMERICO)
; le informazioni per i campi di elaborazione testo
Let gsInfo = LeggeRecord (gsCategoria, sSezione, INFO)
; l'assenso all'immissione di voci su più righe
Let gnMultiple = LeggeNumerico (gsCategoria, sSezione, MULTIPLE)
; la conferma all'uscita dalla procedura
Let gnConferma = LeggeNumerico (gsCategoria, sSezione, CONFERMA)
; il prefisso della funzione da chiamare alla fine della procedura
Let gsChiama = LeggeRecord (gsCategoria, sSezione, CHIAMA)
Return TRUE; se i settaggi si sono conclusi, restituisce l'esito positivo
EndFunction

Esercizio 13.4.2. La funzione VociCampo.

FileScript. Default.JSS

Nome. VociCampo

Descrizione. Carica le voci del campo corrente, ed aggiorna le impostazioni della voce attiva.

Ritorni. Di tipo Int. TRUE, per l'esito regolare del caricamento; FALSE, per interruzioni dovute a errori o procedure da lanciare.

***

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