Tutorial 7: Input dal Mouse
From UIC
Tutorial 7: Input dal mouse
Contents |
| Tutorial 7: Input dal Mouse | |
|---|---|
| Author: | Iczelion |
| Email: | Traduttore: -NeuRaL_NoiSE |
| Website: | Mirror |
| Date: | 01/01/2001 (dd/mm/yyyy) |
| Level: |
|
| Language: | Italian |
| Comments: | |
Introduzione
Impareremo come ricevere input dal mouse e rispondervi nella nostra window procedure. Il programma esempio attendera' i clicks del tasto sinistro del mouse e mostrera' una stringa di testo nel punto esatto della client area in cui l'utente ha clickato.
Preliminari
Come con l'input da tastiera, Windows rileva e notifica le attivita' del mouse che sono rilevanti per ciascuna finestra. Tali attivita' includono clicks del tasto sinistro e destro, movimenti del puntatore nella finestra, doppi clicks. Diversamente dall'input da tastiera che e' diretto alla finestra che detiene l'input focus, i messaggi del mouse sono inviati a qualsiasi finestra su cui si trova il puntatore del mouse, sia essa attiva o non. In piu', ci sono messaggi del mouse relativi anche alla non-client area. Ma la maggior parte delle volte, possiamo tranquillamente ignorarli. Possiamo focalizzare la nostra attenzione su quelli relativi alla client area. Per ciascun tasto, sinistro e destro, del mouse, ci sono due messaggi associati: WM_LBUTTONDOWN, WM_RBUTTONDOWN e WM_LBUTTONUP, WM_RBUTTONUP. Per un mouse a tre tasti, ci sono in piu' WM_MBUTTONDOWN e WM_MBUTTONUP. Quando il puntatore del mouse si muove all'interno della client area, Windows manda messaggi WM_MOUSEMOVE alla finestra relativa. Una finestra puo' ricevere messaggi di doppio click, WM_LBUTTONDBCLK o WM_RBUTTONDBCLK, se e solo se la sual window class e' stata istruita a riceverli, tramite l'inclusione della flag CS_DBLCLKS nel class style, altrimenti la finestra ricevera' soltanto una serie di "mouse button up" e "mouse button down". Per tutti questi messaggi, il valore di lParam equivale alla posizione del mouse. La low word e' la coordinata x, e la high word e' la coordinata y, relative all'angolo superiore sinistro della client area della finestra. wParam indica lo stato dei tasti del mouse e dei tasti Shift e Ctrl.
Contenuto
includelib user32.lib
includelib kernel32.lib
includelib gdi32.lib
.data
ClassName db "SimpleWinClass",0
AppName db "Our First Window",0
MouseClick db 0 ; 0=non si e' ricevuto ancora nessun click
.data?
hInstance HINSTANCE ?
CommandLine LPSTR ?
hitpoint POINT <>
.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 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_LBUTTONDOWN
mov eax,lParam
shl eax,16
shr eax,16
mov hitpoint.x,eax
mov eax,lParam
shr eax,16
mov hitpoint.y,eax
mov MouseClick,TRUE
invoke InvalidateRect,hWnd,NULL,TRUE
.ELSEIF eax==WM_PAINT
invoke BeginPaint,hWnd, ADDR ps
mov hdc,eax
.IF MouseClick
invoke lstrlen,ADDR AppName
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax
.ENDIF
invoke EndPaint,hWnd, ADDR ps
.ELSE
invoke DefWindowProc,hWnd,uMsg,wParam,lParam
ret
.ENDIF
xor eax,eax
ret
WndProc endp
end start
E' ora di analizzare il programma.
mov eax,lParam
and eax,0FFFFh ; comment
mov hitpoint.x,eax
mov eax,lParam
shr eax,16
mov hitpoint.y,eax
mov MouseClick,TRUE
invoke InvalidateRect,hWnd,NULL,TRUE
La window procedure attende un click dal tasto sinistro del mouse. Quando riceve il messaggio WM_LBUTTONDOWN, lParam contiene le coordinate del puntatore del mouse nella client area. Le coordinate vengono salvate in una variabile di tipo POINT che e' definita cosi':
x dd ?
y dd ?
POINT ENDS
e cambia la flag, MouseClick, in TRUE, a significare che c'e' stato almeno un click del tasto sinistro del mouse nella client area.
and eax,0FFFFh
mov hitpoint.x,eax
Poiche' la coordinata x e' la low word di lParam e i membri della struttura POINT sono a 32-bits come dimensioni, noi dobbiamo azzerare la high word di eax prima di conservarla in hitpoint.x.
mov hitpoint.y,eax
E poiche' la coordinata y e' la high word di lParam, dobbiamo metterla nella low word di eax prima di conservarla in hitpoint.y. Facciamo cio' spostando (shifting) eax di 16 bit a destra (con shr). Dopo aver salvato la posizione del mouse, settiamo la flag, MouseClick, a TRUE per far si che le istruzioni di "scrittura" nella sezione WM_PAINT sappiano che c'e' stato almeno un click nella client area, e di conseguenza disegnino la stringa alla posizione del mouse. Successivamente chiamiamo la funzione InvalidateRect per costringere la finestra a ridisegnare la sua intera client area.
invoke lstrlen,ADDR AppName
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax
.ENDIF
Le istruzioni di scrittura nella sezione WM_PAINT devono controllare se MouseClick e' TRUE, dal momento che quando la finestra e' stata creata, ha ricevuto ugualmente un messaggio WM_PAINT, ma in quel momento non c'era stato nessun click e quindi non doveva disegnare la stringa nella client area. Pertanto noi inizializziamo MouseClick come FALSE e cambiamo il suo valore in TRUE quando l'utente clicka effettivamente il tasto sinistro del mouse. Se c'e' stato almeno un click del mouse, il codice disegna la stringa nella client area alla posizione del mouse. Notate che chiamiamo lstrlen per ottenere la lunghezza della stringa da mostrare, e utilizziamo tale lunghezza come ultimo parametro della funzione TextOut.
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 malevole 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.