Per dubbi, consigli o richieste, potete mandare un'e-mail ad Andrea Carolfi.
Ringraziamo Amiga Transactor Mailing List per questo tangibile contributo!
In questa lezione concluderemo il discorso sui menù di Intuition.
Nella puntata precendente abbiamo visto la loro creazione e rimozione, in
questa vedremo la loro gestione. IntuiMessage e menù Come vi avevo spiegato un pò di lezioni fa, Intuition "impacchetta"
il numero di menù, opzione e sotto opzione in un numero a 16bit che
restituisce nel campo Code della struttura IntuiMessage ogni
qualvolta l'utente seleziona un menù (sempre che sia stato deciso di
ascoltare questo tipo di evento).
Un ciclo di gestione potrebbe quindi essere: while(!finito) { WaitPort(win -> UserPort); while((msg = GT_GetIMsg(win -> UserPort))) { switch(msg -> Class) { case IDCMP_CLOSEWINDOW: finito = TRUE; break; case IDCMP_MENUPICK: switch(MENUNUM(msg -> Code)) { case 0: switch(ITEMNUM(msg -> Code)) { case 0: Printf("1a opzione del 1o menù!\n"); break; case 1: Printf("2a opzione del 1o menù!\n"); break; case 2: Printf("3a opzione del 1o menù!\n"); break; case 3: Printf("4a opzione del 1o menù!\n"); break; case 4: Printf("5a opzione del 1o menù!\n"); break; } break; case 1: Printf("Secondo menù!\n"); break; case 2: Printf("Terzo menù!\n"); break; } [...] Un altro modo potrebbe essere: while(!finito) { WaitPort(win -> UserPort); while((msg = GT_GetIMsg(win -> UserPort))) { switch(msg -> Class) { case IDCMP_CLOSEWINDOW: finito = TRUE; break; case IDCMP_MENUPICK: switch(msg -> Code) { case FULLMENUNUM(0,1,NOSUB): Printf("1a opzione 1o menù!\n"); break; case FULLMENUNUM(1,1,NOSUB): Printf("2a opzione 2o menù!\n"); break; } [...] Entrambi i modi sono equivalenti, il primo è forse più didattico ma prolisso, il secondo più compatto. Comunque, il secondo metodo può essere ulteriormente raffinato grazie alle comode define, ad esempio: #define PROGETTO_SALVA FULLMENUNUM(0,3,NOSUB) #define OPZIONI_CARICA FULLMENUNUM(2,1,NOSUB) [...] case IDCMP_MENUPICK: switch(msg -> Code) { case PROGETTO_SALVA: /* Devo salvare il progetto */ SalvaProgetto(); break; [...] case OPZIONI_CARICA: /* Devo caricare le opzioni da disco */ CaricaOpzioni(); break; [...] Che mi sembra molto leggibile. In questo discorso di MENUNUM ITEMNUM e altro, rientrano pienamente
le funzioni OnMenu e OffMenu che avevo introdotto nella lezione
precedente senza dargli un approfondimento maggiore. In questa lezione, spiego
che, come il nome lascia intendere, la OffMenu permette di disabilitare
e quindi rendere inacessibile un opzione di menù o anche un intero
menù che potranno essere abilitati con la controparte della funzione,
OnMenu. Rimane da spiegare, per chi ha dato un'occhiata al
sorgente allegato , cosa sono quegli strani
~(1 << 5). Penso che tutti sapranno che è uno shiftamento
a sinistra di 1 di 5 posizioni e di una negazione, ma credo che non tutti
avranno capito a cosa serve. Avrete certamente notato che solo tre opzioni
hanno questo valore impostato che non è nemmeno lo stesso e che sono
gli unici ad avere i flag MENUTOGGLE e CHECKIT abilitati. Questo
valore infatti serve se vogliamo creare una serie di opzioni in mutua
esclusione tra di loro; come nell'esempio tra IFF, Testo e 8SVX. Il valore
indica a quali opzioni togliere il simbolo di vista quando quell'opzione
è selezionata. Infatti, nel caso di IFF, lo shiftamento di 1 di 5
posizioni indicherebbe proprio l'opzioni IFF (la sesta di quel menù),
ma creando il NOT, diventa: tutte le altre tranne quella. Infine, abbiamo la funzione ItemAddress. Questa funzione serve per ricevere un puntatore alla struttura MenuItem dell'opzione corrispondente al parametro passato. struct MenuItem *ItemAddress(struct Menu *menu,UWORD menunumber); Per esempio, chiamando
ItemAddress(win -> MenuStrip,PROGETTO_SALVA), mi restituirà
il puntatore alla struttura MenuItem relativa alla quarta opzione
del primo menù. Inoltre nella gestione degli eventi per gestire la
multi selezione. Vi ricordate il campo NextSelect della struttura
MenuItem? case IDCMP_MENUPICK: { UWORD code = msg -> Code; do { struct Menuitem *item; switch(code) { case PROGETTO_SALVA: /* Devo salvare il progetto */ SalvaProgetto(); break; [...] } item = ItemAddress(win -> MenuStrip,code); code = item -> NextSelect; } while(code != MENUNULL); [...] |
![]() |
![]() |