Bajar el ejemplo de aquí.
Como con la entrada del teclado, Windows detecta y envía notificaciones sobre las actividades del ratón que son relevantes para las ventanas. Esas actividades incluyen los clicks de los botones izquierdo y derecho del ratón, el movimiento del cursor del ratón sobre la ventana, doble clicks. A diferencia de la entrada del teclado, que es dirigida a la ventana que tiene el foco de entrada, los mensajes del ratón son enviados a cualquier ventana sobre la cual esté el cursor del ratón, activo o no. Además, también hay mensajes del ratón sobre el área no cliente. Pero la mayoría de las veces, afortunademente podemos ignorarlas. Podemos concentrarnos en los mensajes relacionados con el área cliente.
Hay dos mensajes para cada botón el ratón: los mensajes WM_LBUTTONDOWN, WM_RBUTTONDOWN y WM_LBUTTONUP, WM_RBUTTONUP. Para un ratón con tres botones, están también WM_MBUTTONDOWN and WM_MBUTTONUP. Cuando el cursor del ratón se mueve sobre el área cliente, Windows envía mensajes WM_MOUSEMOVE a la ventana debajo del cursor. Una ventana puede recibir mensajes de doble clicks, WM_LBUTTONDBCLK o WM_RBUTTONDBCLK, si y sólo si la clase de su ventana tiene activada la bandera correspondiente al estilo CS_DBLCLKS, sino la ventana recibirá sólo una serie de mensajes del topo botón del ratón arriba o abajo.
Para todos
estos mensajes, el valor de lParam contiene la posición del ratón.
La palabra [word] baja es la coordenada 'x', y la palabra alta es la coordenada
'y' relativa a la esquina izquierda superior del área cliente de la ventana.
wParam indica el estado de los botones del ratón y de las teclas Shift
y Ctrl.
WinMain proto :DWORD,:DWORD,:DWORD,:DWORD
include
\masm32\include\windows.inc
include
\masm32\include\user32.inc
include
\masm32\include\kernel32.inc
include
\masm32\include\gdi32.inc
includelib
\masm32\lib\user32.lib
includelib
\masm32\lib\kernel32.lib
includelib
\masm32\lib\gdi32.lib
.data
ClassName
db "SimpleWinClass",0
AppName
db "Our First Window",0
MouseClick
db 0 ; 0=no click yet
.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:DWORD
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 hInst
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,eax
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
.IF uMsg==WM_DESTROY
invoke PostQuitMessage,NULL
.ELSEIF uMsg==WM_LBUTTONDOWN
mov eax,lParam
and eax,0FFFFh
mov hitpoint.x,eax
mov eax,lParam
shr eax,16
mov hitpoint.y,eax
mov MouseClick,TRUE
invoke InvalidateRect,hWnd,NULL,TRUE
.ELSEIF uMsg==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
El procedimiento de ventana espera a que el botón izquierdo del ratón haga un click. Cuando recibe el mensaje WM_LBUTTONDOWN, lParam contiene la coordenada del botón del ratón en el área cliente. Salva la coordenada en la variable de tipo POINT definida así:
POINT
STRUCT
x dd ?
y dd ?
POINT
ENDS
y establece la bandera, MouseClick, a TRUE, lo que siginifica que al menos hay un click del botón izquierdo del ratón sobre el área cliente.
mov eax,lParam
and eax,0FFFFh
mov hitpoint.x,eax
Como la coordenada 'x' es la palabra baja de lParam y los miembros de la estructura POINT tiene un tamaño de 32-bits, debemos poner en cero la palabara alta de eax antes de almacenarla en hitpoint.x.
shr eax,16
mov hitpoint.y,eax
Como la coordenada 'y' es la palabra alta de lParam, debemos ponerla en la palabra baja de eax antes de almacenarla en hitpoint.y. Hacemos esto desplazando [shifting] el contenido de eax 16 bits a la derecha.
Después de almacenar la posición del ratón, establecemos la bandera, MouseClick, a TRUE con el fin de dejar que el código de pintura en la sección WM_PAINT sepa que hay al menos un click en el área cliente y puede dibujar la cadena en la posición del ratón. Luego llamamos a la función InvalidateRect para que Windows vuelva a pintar toda el área cliente.
.IF MouseClick
invoke lstrlen,ADDR AppName
invoke TextOut,hdc,hitpoint.x,hitpoint.y,ADDR AppName,eax
.ENDIF
El código de pintura en la sección WM_PAINT debe chequear si MouseClick es uno ( TRUE ), ya que cuando la ventana fue creada, recibió un mensaje WM_PAINT en ese momento, ningún click del ratón había ocurrido aún, así que no dibujará la cadena en el área cliente. Inicializamos MouseClick a FALSE y cambiamos su valor a TRUE cuando ocurre un click del ratón.
Si ha ocurrido
al menos un click de ratón, se dibuja la cadena en el área cliente
en la posición del ratón. Nota que se llama a lstrlen para obtener
el tamaño de la cadena a desplegar y envía este tamaño
como último parámetro de la función TextOut.
[Iczelion's Win32 Assembly HomePage]
n u M I T_o r's Programming Page
Este tutorial, original de Iczelion, ha sido traducido por: n u M I T_o r