Articolo pubblicato sul n. 67 di MCmicrocomputer (Edizioni Technimedia Srl - Roma) nell'ottobre 1987
Amighevole: Sempre a proposito dell'AmigaBasic, questo mese parleremo dei menu a discesa e delle interruzioni. Coi primi sar possibile "abbellire" i propri programmi dotandoli, con poco sforzo, di una interfaccia intuitiva e, tramite mouse, anche molto veloce. Col meccanismo delle interruzioni potremo controllare facilmente, a programma, alcuni eventi esterni. Il motivo per cui trattiamo insieme i due argomenti presto detto: uno degli eventi esterni gestibili come interrupt appunto la scelta da menu a discesa...
Prologo
Alcune settimane fa, sono arrivate in redazione un paio di "amighevoli" lettere nelle quali i rispettivi autori contestavano il fatto che su MC microcomputer si sprecasse spazio editoriale per parlare dell'AmigaBasic, secondo loro, ampiamente trattato gi sul manuale fornito con la macchina. A dire il vero, qualche mese fa anche il sottoscritto la pensava alla stessa maniera, e il ciclo di articoli relativi all'AmigaBasic ha preso vita solo "a gentile richiesta" di numerosi lettori che si trovavano in difficolt con questo linguaggio. Preso poi seriamente in mano il manuale, bisogna riconoscere che alcune cose sono spiegate particolarmente male e si riesce a venirne a capo solo dopo svariati tentativi falliti...
Menu a discesa
I menu a discesa definibili da AmigaBasic funzionano esattamente come quelli del Workbench. Premendo il tasto destro del mouse facciamo apparire la barra superiore contenente i nomi dei singoli menu, in questa condizione, portando il mouse su uno di questi nomi vedremo apparire le varie opzioni che abbiamo programmato. Come accade nel Workbench, alcune di queste (o un intero menu) potranno essere non attive, nel tal caso appariranno un po' meno leggibili. Come prevedibile, l'istruzione che permette la creazionz di un nuovo menu MENU, nella sintassi:
MENU numero,item,stato,stringa
dove "numero" il numero del menu (si conta da destra verso sinistra cominciando da 1); "item" la posizione nel menu appena indicato (la posizione 0 il nome del menu); "stato" indica appunto se l'item o l'intero menu attivo (1) o non attivo (0); "stringa", infine, la stringa da associare a quella determinata posizione del menu, o il titolo del menu stesso. Per cambiare stato ad un menu gi definito indicheremo solo i primi tre valori. Ad esempio, per disabilitare la terza scelta del secondo menu (precedentemente definito) scriveremo:
MENU 2,3,0
Ricordando che lo schermo di default il normale schermo di output dell'AmigaBasic se dopo aver giocato un po' coi menu vogliamo ritornare alle condizioni iniziali, digiteremo:
MENU RESET
Le funzioni di lettura
Per conoscerre, da programma, cosa ha selezionato l'operatore esistono due funzioni, MENU(0) e MENU(1), che restituiscono rispettivamente il numero del menu e (all'interno di questo) il numero dell'item selezionato. Quando l'operatore non sta selezionando niente, MENU(0) vale 0 dunque possibile eseguire dei cicli di attesa finch... non succede qualcosa. Il listato 1 una prima, banale, applicazione dei comandi test discussi. Come facile notare, la prima parte del listatino serve per definire due menu a discesa. Seguono due istruzioni per far "scomparire" i menu 'Run' e 'Window' del basic. Nel ciclo infinito While...Wend dopo aver stampato su video la variabile I, incrementata ogni volta, viene interrogata la funzione MENU(0). Si usa la variabile temporanea 'm' essendo interessati a congelarne la lettura (riutilizzeremo tale valore all'interno della subruotine). Cos, se MENU(0) diverso da zero saltiamo alla subroutine che non fa altro che stampare, utilizzando anche MENU(1), la scelta effettuata. L'effetto finale sar dunque uno "scrollare" di numeri via via cresccenti intervallati dalle nostre scelte se utilizzeremo i menu. Non serve assolutamente a niente ma funziona...funziona!!!...FUNZIONA!!!!!!!
Le interruzioni
Giacch siamo in tema di menu, e come abbiamo detto la scelta da menu pu essere trattata come un interrupt, entriamo immediatamente in argomento modificando il programmino 1 secondo il nuovo schema. Il tutto mostrato nel listato 2: le modifiche sono minime, ma rendono tutto il listato notevolmente pi leggibile. Specialmente una volta chiarito il significato dei comandi ON MENU e MENU ON... A proposito, siamo sicuri che tutti sanno cos' una interruzione ? Immaginate un normale programma in esecuzione. Cosa stia facendo in quel momento il programma a noi non interessa: diciamo che "gira" e basta. L'interruzione pi banale , non a caso, il comando di stop del programma: quando "questo meno se l'aspetta" un bel Control C fa terminare anzitempo l'esecuzione. Da sottolineare l'asincronicit dell'evento, occorso non in un particolare momento dell'esecuzione ma in un istante qualsiasi (traduzione: ricominciando tutto daccapo e dando nuovamente il Control C, in generale, fermeremo l'esecuzione del programma in un punto differente dal precedente). Questo come caso banale. Molto probabilmente, infatti, non siamo interessati solo ad interruzioni "totali", ma anche a interruzioni meno "dolorose": al verificarsi di un determinato evento, desideriamo che sia eseguita una particolare procedura detta appunto di manipolazione dell'interruzione. Terminata tale procedura, il corso dell'elaborazione dovr continuare dallo stesso punto dove era stato interrotto, in un certo senso, come se nulla fosse successo, a meno che l'interruzione (o, meglio, la routine di manipolazione dell'interruzione) non abbia provocato essa stessa un cambiamento di stato. Le interruzioni controllabili da AmigaBasic sono in tutto 5 e riguardano la scelta da menu, la pressione del tasto sinistro del mouse, la collisione tra sprite (che non tratteremo in questa sede), il gi citato Control C (o stop da menu) e il timer interno col quale possibile implementare un mini multitasking all'interno di un programma basic. Per abilitare il meccanismo di rilevamento e trattamento delle interruzioni si definisce inizialmente il "da farsi" in caso di interrupt. Quando, in un certo senso, siamo pronti a trattare gli interrupt, nel nostro programma utilizzeremo il comando di abilitazione vera e propria. Per definire il "da farsi" si usa il comando:
ON <evento> GOSUB <subroutine>
che sta proprio ad indicare: 'in caso di <evento> devi saltare a <subroutine>'. Per abilitare il rivelamento useremo il comando:
<evento> ON
per disabilitare:
<evento> OFF
<evento> potr essere una delle 4 parole chiave: MENU, MOUSE, TIMER e BREAK, mentre <subroutine> il nome o il numero linea di una subroutine posta in qualsiasi punto del programma e come tale (mi raccomando) dotata di RETURN finale. Nella subroutine in questione scriveremo le linee di programma che implementano il vero e proprio trattamento della interruzione. Tornando al listato 2 possiamo ora interpretare correttamente il significato di quelle linee di programma. Con:
ON MENU GOSUB Scelta
diciamo che (quando avremo dato l'ordine di "ascoltare" gli interrupt) ad ogni accesso ai menu a discesa dovremo saltare alla subroutine "Scelta". Con:
MENU ON
abilitiamo il rilevamento degli interrupt. Si noti come il ciclo infinito While...Wend questa volta si preoccupi solo di stampare i numerini via via crescenti: il sistema che provveder automaticamente a fermare la stampa in caso di selezione da menu (deve infatti essere eseguita la subroutine "Scelta"). Tutto qui.
Control C
Che il Control C sia un interrupt l'abbiamo gi appurato un po righe fa. Da AmigaBasic possibile controllarlo e trattarlo come qualsiasi altra interruzione. Il listato 3 ne un esempio: l'evanto si chiama BREAK e, come prima, usiamo un comando per definire dove saltare in caso di interrupt:
ON BREAK GOSUB stampa
e un secondo comando per abilitare il rilevamento:
BREAK ON
Il risultato di tutto il programma sar il solito scrollare di numeri, intervallati da un messaggio all'operatore quando questo tenta di fermarne l'esecuzione. Per la cronaca, l'unico modo per fermarlo sar chiudere tutte le finestre relative al lancio dell'AmigaBasic.
Mouse e affini
Il terzo tipo di interrupt riguarda la pressione del tasto sinistro del mouse. Grazie a questa possibilit diventa molto facile utilizzare l'interfaccia mouse & pointer anche per i nostri programmi. Ad esempio selezionare col topo alcuni oggetti sullo schermo, effettuare spostamenti (s, pensate pure ad una partita a scacchi) o altro. Il metodo sempre lo stesso: scriviamo da qualche parte nel nostro programma la subroutine che dovr trattare l'interruzione da mouse, e con i due comandi, di dichiarazione e di attivazione, diamo inizio al "trattamento". Come per i menu, esiste una funzione MOUSE() che, a seconda dell'argomento passato, restituisce lo stato del dispositivo. Senza scendere troppo nei dettagli, che comunque troverete nel manuale fornito con la macchina, diremo che MOUSE(0) usato per conoscere lo stato del pulsante sinistro, MOUSE(1) e MOUSE(2) la posizione attuale del mouse, MOUSE(3) e MOUSE(4) la posizione iniziale di un movimento, MOUSE(5) e MOUSE(6) quella finale. Tutti questi valori sono aggiornati solo dopo ogni lettura di MOUSE(0), sar quindi questa la prima operazione da compiere prima di leggere le varie coordinate. Il programma di listato 4 una prima applicazione: dando RUN a questo vedremo i soliti stamaledettissimi numerini che scrollano, intervallati dalla posizione attuale del mouse ogni volta che premiamo il tasto sinistro del mosue che provoca l'interrupt. Le coordinate del mouse sono sempre espresse in pixel, con punto d'origine nell'angolo superiore sinistro dello schermo. Da notare la prima linea delle subroutine "leggi":
a=MOUSE(0)
indispensabile per leggere correttamente le coordinate alla linea successiva. Il listato 5 mostra un'applicazione dei rimanenti valori passati alla funzione MOUSE. Questa volta (i numerini vi sono stati risparmiati), tenendo premuto il pulsante, tracciando col mouse un percorso qualsiasi, il programma traccier una linea retta tra i punti iniziali e finali del movimento. Provare per credere...
Timer
L'ultima interruzione che tratteremo riguarda il timer interno all'Amiga. Da AmigaBasic potremo programmare il timer affinch ci invii interrupt ad intervalli di tempo prefissati. L'indicazione del quanto di tempo, espresso in secondi, avviene nello stesso momento in cui dichiariamo di voler utilizzare il timer. Nel listato 6, ad esempio, il timer settato per intervalli pari ad un secondo, nel listato 7 l'intervallo tra un interrupt e un altro fissato pari a mezzo secondo. Nel listato 6 i soliti numerini sarranno intervallati dall'indicazione "interrupt!" ogni secondo, nel listato sette abbiamo inserito l'emissione di una nota random (prendano "nota" coloro i quali sono interessati a inserire musichette nei loro giochini) ogni mezzo secondo. Una volta dato il RUN ad uno di questi due programmi, provando a cambiare la dimensione della finestra in cui avviene lo scroll dei numerini noterete, come era prevedibile, che le interruzioni non dipendono dal numero di numerini stampati (come noto con finestre piu' piccole lo scroll avviene piu' velocemente e quindi anche i programmi vanno pi veloci quando devono stampare qualcosa) ma solo e soltanto dal tempo. Grazie e arrivederci. Articolo pubblicato su www.digiTANTO.it - per ulteriori informazioni clicca qui |