Tutorial 6: Input dalla Tastiera
From UIC
Tutorial 6: Input dalla Tastiera
Contents |
| Infos | |
|---|---|
| Author: | Iczelion |
| Email: | Traduttore: -NeuRaL_NoiSE |
| Website: | Mirror |
| Date: | 01/01/2001 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| Comments: | |
Introduzione
Impareremo come fa Windows a ricevere input dalla tastiera.
Preliminiari
Dal momento in cui c'e' solo una tastiera in ogni PC, tutti i programmi Windows in esecuzione devono condividerla. Windows e' responsabile per l'invio dell'input di pressione del tasto alla finestra che detiene l'input focus (quando un cursore lampeggia in un box, si dice che quel box ha l' "input focus", NdT). Nonostante possono coesistere diverse finestre sullo schermo, solo una di esse ha l'input focus. La finestra che ha l'input focus e' l'unica che puo' ricevere l'input dai tasti. Potete distinguere la finestra che ha l'input focus dalle altre osservando la sua barra del titolo, che e' evidenziata. In realta', ci sono due tipi principali di messaggi da tastiera. Potete considerare una tastiera come un gruppo di tasti. Per esempio, se premete il tasto "a", Windows manda un messaggio WM_KEYDOWN alla finestra che ha l'input focus, notificando che un tasto e' stato premuto. Quando sollevate il dito dal tasto, Windows manda un messaggio WM_KEYUP. In questo caso, trattate un tasto come se fosse un bottone. Un altro modo di considerare la tastiera e' vederla come un periferica grazie alla quale si ricevono dei caratteri come input. Quando premete il tasto "a", Windows manda un messaggio WM_CHAR alla finestra che ha l'input focus, dicendole che l'utente le sta inviando un carattere "a". Infatti, Windows manda i messaggi WM_KEYDOWN, WM_CHAR, e WM_KEYUP alla finestra che ha l'input focus. La window procedure puo' decidere se elaborare tutti e tre i messaggi o solo quelli a cui e' interessata. La maggior parte delle volte, potrete ignorare WM_KEYDOWN e WM_KEYUP dal momento che la funzione TranslateMessage nel message loop traduce i messaggi WM_KEYDOWN e WM_KEYUP in un messaggio WM_CHAR. Noi ci concentreremo su WM_CHAR in questo tutorial.
Contenuto
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
char WPARAM 20h // il carattere che il programma riceve dalla tastiera
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
.code
start:
invoke GetModuleHandle, NULL
mov hInstance,eax
invoke GetCommandLine
invoke WinMain, hInstance,NULL,CommandLine, SW_SHOWDEFAULT
invoke ExitProcess,eax
WinMain proc hInst:HINSTANCE,hPrevInst:HINSTANCE,CmdLine:LPSTR,CmdShow:SDWORD
LOCAL wc:WNDCLASSEX
LOCAL msg:MSG
LOCAL hwnd:HWND
mov wc.cbSize,SIZEOF WNDCLASSEX
mov wc.style, CS_HREDRAW or CS_VREDRAW
mov wc.lpfnWndProc, OFFSET WndProc
mov wc.cbClsExtra,NULL
mov wc.cbWndExtra,NULL
push hInstance
pop wc.hInstance
mov wc.hbrBackground,COLOR_WINDOW+1
mov wc.lpszMenuName,NULL
mov wc.lpszClassName,OFFSET ClassName
invoke LoadIcon,NULL,IDI_APPLICATION
mov wc.hIcon,eax
mov wc.hIconSm,0
invoke LoadCursor,NULL,IDC_ARROW
mov wc.hCursor,eax
invoke RegisterClassEx, addr wc
invoke CreateWindowEx,NULL,ADDR ClassName,ADDR AppName,\
WS_OVERLAPPEDWINDOW,CW_USEDEFAULT,\
CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,NULL,NULL,\
hInst,NULL
mov hwnd,eax
invoke ShowWindow, hwnd,SW_SHOWNORMAL
invoke UpdateWindow, hwnd
.WHILE TRUE
invoke GetMessage, ADDR msg,NULL,0,0
.BREAK .IF (!eax)
invoke TranslateMessage, ADDR msg
invoke DispatchMessage, ADDR msg
.ENDW
mov eax,msg.wParam
ret
WinMain endp
WndProc proc hWnd:HWND, uMsg:UINT, wParam:WPARAM, lParam:LPARAM
LOCAL hdc:HDC
LOCAL ps:PAINTSTRUCT
mov eax,uMsg
.IF eax==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF eax==WM_CHAR
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
.ELSEIF eax==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
invoke TextOut,hdc,0,0,ADDR char,1
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
Analizziamo il codice
Questa e' la variabile che conserva il carattere ricevuto dalla tastiera. Dal momento che il carattere e' inviato al WPARAM della window procedure, noi definiamo la variabile di tipo WPARAM per semplicita'. Il valore iniziale e' 20h (spazio) poiche' quando la nostra finestra "rinfresca" la sua client area la prima volta, non c'e' nessun input di caratteri. Percio' noi mostreremo uno spazio.
push wParam
pop char
invoke InvalidateRect, hWnd,NULL,TRUE
Questa parte e' aggiunta alla window procedure per gestire il messaggio WM_CHAR. Essa semplicemente mette il carattere nella variabile "char" e quindi chiama InvalidateRect. InvalidateRect rende invalido uno specifico rettangolo della client area, la qual cosa obbliga Windows a mandare il messaggio WM_PAINT alla window procedure. La sua sintassi e' questa:
HWND hWnd, // handle della finestra la cui regione deve essere aggiornata
CONST RECT * lpRect, // indirizzo delle coordinate del rettangolo
BOOL bErase // flag "cancella lo sfondo"
);
lpRect e' un puntatore al rettangolo nella client area che vogliamo dichiarare invalido. Se questo parametro e' NULL (=0, NdT), l'intera client area sara' segnata come invalida. bErase e' una flag che comunica a Windows se si deve cancellare lo sfondo. Se questa flag e' TRUE (=1, NdT), Windows cancellera' lo sfondo del rettangolo invalido quando viene chiamata la funzione BeginPaint. Percio' la strategia che abbiamo usato qui e' questa: conserviamo tutte le informazioni necessarie su come disegnare la client area e generiamo il messaggio WM_PAINT per disegnare la client area. Ovviamente, le istruzioni nella sezione WM_PAINT devono sapere cosa ci si aspetta da loro. Questo sembrerebbe una specie di sistema "alternativo" nel fare le cose, una sorta di scappatoia, ma e' cosi' che lavora Windows. In realta' possiamo disegnare nella client area mentre elaboriamo il messaggio WM_CHAR chiamando la coppia di funzioni GetDC e ReleaseDC. Non c'e' problema. Ma il divertimento comincia quando la nostra finestra ha bisogno di ridisegnare la propria client area. Poiche' le istruzioni che disegnano il carattere risiedono nella sezione relativa a WM_CHAR, la window procedure non sara' in grado di ridisegnare il nostro carattere nella client area. Percio' la conclusione e': mettete tutti i dati e le istruzioni necessarie per disegnare sotto WM_PAINT. Potete mandare il messaggio WM_PAINT da qualsiasi posto nel vostro codice in qualsiasi momento vi venga voglia di ridisegnare la vostra client area.
Quando viene chiamata la funzione InvalidateRect, essa restituisce un messaggio WM_PAINT alla window procedure. Di conseguenza vengono eseguite le istruzioni nella sezione WM_PAINT. Questa chiama, come al solito, BeginPaint per trovare l'handle del device context e quindi chiama TextOut che disegna il nostro carattere nella client area alle coordinate x=0, y=0. Quando fate partire il programma e premete un tasto qualsiasi, vedrete il carattere riprodursi nell'angolo superiore sinistro della client window. E quando la finestra viene ridotta ad icona e quindi ingrandita di nuovo, il carattere sta ancora li' poiche' tutte le istruzioni e i dati essenziali per ridisegnarlo risiedono nella sezione WM_PAINT.
Note finali
Questi tutorials erano presenti nel sito di RingZero. Li rimettiamo a disposizione a chiunque voglia poter leggerli nella loro traduzione in italiano che fu curata da NeuralNoise.
phobos
Disclaimer
I documenti qui pubblicati sono da considerarsi pubblici e liberamente distribuibili, a patto che se ne citi la fonte di provenienza. Tutti i documenti presenti su queste pagine sono stati scritti esclusivamente a scopo di ricerca, nessuna di queste analisi è stata fatta per fini commerciali, o dietro alcun tipo di compenso. I documenti pubblicati presentano delle analisi puramente teoriche della struttura di un programma, in nessun caso il software è stato realmente disassemblato o modificato; ogni corrispondenza presente tra i documenti pubblicati e le istruzioni del software oggetto dell'analisi, è da ritenersi puramente casuale. Tutti i documenti vengono inviati in forma anonima ed automaticamente pubblicati, i diritti di tali opere appartengono esclusivamente al firmatario del documento (se presente), in nessun caso il gestore di questo sito, o del server su cui risiede, può essere ritenuto responsabile dei contenuti qui presenti, oltretutto il gestore del sito non è in grado di risalire all'identità del mittente dei documenti. Tutti i documenti ed i file di questo sito non presentano alcun tipo di garanzia, pertanto ne è sconsigliata a tutti la lettura o l'esecuzione, lo staff non si assume alcuna responsabilità per quanto riguarda l'uso improprio di tali documenti e/o file, è doveroso aggiungere che ogni riferimento a fatti cose o persone è da considerarsi PURAMENTE casuale. Tutti coloro che potrebbero ritenersi moralmente offesi dai contenuti di queste pagine, sono tenuti ad uscire immediatamente da questo sito.
Vogliamo inoltre ricordare che il Reverse Engineering è uno strumento tecnologico di grande potenza ed importanza, senza di esso non sarebbe possibile creare antivirus, scoprire funzioni malevoli e non dichiarate all'interno di un programma di pubblico utilizzo. Non sarebbe possibile scoprire, in assenza di un sistema sicuro per il controllo dell'integrità, se il "tal" programma è realmente quello che l'utente ha scelto di installare ed eseguire, né sarebbe possibile continuare lo sviluppo di quei programmi (o l'utilizzo di quelle periferiche) ritenuti obsoleti e non più supportati dalle fonti ufficiali.
Categories: Assembly | Iczelion | 2001