No he encontrado un tema que lo explique así que hago mi pregunta:
Estoy usando FASM y programando en Windows modo gráfico.
Quiero leer la posición del ratón y comprobar si se encuentra dentro de un area al hacer click. He echo esto:
Definición de las variables
punto POINT
cPosx1 dd ?
cPosy1 dd ?
cPosx2 dd ?
cPosy2 dd ?
posicionx1 dd ?
posicionx2 dd ?
posiciony1 dd ?
posiciony2 dd ?
Luego mediante el mensaje WM_LBUTTONDOWN hago lo siguiente
_mouse_click:
invoke GetCursorPos, punto ;Comprobamos las coordenadas del cursor
;y lo guardamos en la estructura punto
mov eax, [cPosx1] ;Punto izquierdo del area
cmp [punto.x], eax ;Compara "X" del cursor con punto izquierdo del area
jl _final ;si es inferior no sigue.
mov eax, [cPosx2] ;Punto derecho del area
cmp [punto.x], eax ;Compara "X" del cursor con punto derecho del area
ja _final ;si es superior no sigue.
mov eax, [cPosy1] ;Punto superior del area
cmp [punto.y], eax ;Compara "Y" del cursor con punto superior del area
jl _final ;si es inferior no sigue.
mov eax, [cPosy2] ;Punto inferior del area
cmp [punto.y], eax ;Compara "Y" del cursor con punto inferior del area
ja _final ;si es superior no sigue.
En principio la comprobación está bien; sin envargo cuando hago click con el ratón, las coordenadas siempre son inferiores a las del area, aunque haga click dentro del area.
El area está dibujada mediante un procedimiento y por lo tanto lo veo y puedo hacer click dentro del mismo, pero las coordenadas devueltas siempre son inferiores a las del area y no tengo ni idea del motivo. :-[
Aquí os dejo el código entero excepto donde hay gráficos para que podais copiar-pegar y ejecutarlo si quereis:
format PE GUI
entry comienzo
include 'win32a.inc'
cdxPos EQU 128
cdyPos EQU 128
cdxTamano EQU 800
cdyTamano EQU 600
cdColFondo EQU 002h
cdIcono EQU IDI_APPLICATION
cdCursor EQU IDC_ARROW
cdTipoBar EQU 0; WS_EX_CLIENTEDGE :Borde alrededor de la ventana.
cdTipoBoton EQU WS_VISIBLE + WS_DLGFRAME
id_Muralla_H EQU 100
id_Muralla_VI EQU 101
id_Muralla_VD EQU 102
id_Muralla_EI EQU 103
id_Muralla_ED EQU 104
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Sección de datos ++
;++++++++++++++++++++++++++++++++++++++++++++++++
section '.data' data readable writeable
NombreClase db 'VentanaSimple', 0
Titulo db 'Editor de ciudad v.0.0', 0
ErrorRegistro db 'Error al Registrar', 0
ErrorCrear db 'Error al Crear', 0
CommandLine dd ?
wc WNDCLASS 0, WindowProc, 0, 0, 0, 0, 0, cdColFondo, 0, NombreClase
msg MSG
punto POINT
ps PAINTSTRUCT
rect RECT
Posx dd ?
Posy dd ?
Posy2 dd ?
Posy3 dd ?
Posy4 dd ?
Posy5 dd ?
hMuralla_H rd 1
hMuralla_VI rd 1
hMuralla_VD rd 1
hMuralla_EI rd 1
hMuralla_ED rd 1
id_Elegido rd 1
hPen dd ?
hPenOld dd ?
cPosx1 dd ?
cPosy1 dd ?
cPosx2 dd ?
cPosy2 dd ?
posicionx1 dd ?
posicionx2 dd ?
posiciony1 dd ?
posiciony2 dd ?
hdc rd 1
hMemDC rd 1
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Sección ejecutable ++
;++++++++++++++++++++++++++++++++++++++++++++++++
section '.text' code readable executable
comienzo:
invoke GetModuleHandle, 0
mov [wc.hInstance], eax
invoke GetCommandLine
mov [CommandLine], eax
invoke LoadCursor, 0, cdCursor
mov [wc.hCursor], eax
invoke LoadIcon, 0, cdIcono
mov [wc.hIcon], eax
invoke RegisterClass, wc
test eax, eax
jne _principal
invoke MessageBox, 0, ErrorRegistro, 0, MB_OK + MB_ICONERROR
_principal:
stdcall WinMain, [wc.hInstance], 0, [CommandLine], SW_SHOWNORMAL
invoke ExitProcess, 0
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Procedimiento principal del programa ++
;++++++++++++++++++++++++++++++++++++++++++++++++
proc WinMain uses ebx esi edi, hInst, hPrevInst, CmdLine, CmdShow
invoke CreateWindowEx,\
cdTipoBar,\
NombreClase,\
Titulo,\
cdTipoBoton,\
cdxPos,\
cdyPos,\
cdxTamano,\
cdyTamano,\
0,\
0,\
[hInst],\
0
test eax, eax
jne _msg_loop
invoke MessageBox, 0, ErrorCrear, 0, MB_OK + MB_ICONERROR
_msg_loop:
invoke GetMessage, msg, 0, 0, 0
cmp eax, 1
jb _end_loop
jne _msg_loop
invoke TranslateMessage, msg
invoke DispatchMessage, msg
jmp _msg_loop
_end_loop:
ret
endp
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Procedimiento de los mensajes principal ++
;++++++++++++++++++++++++++++++++++++++++++++++++
proc WindowProc uses ebx esi edi, hwnd, wmsg, wparam, lparam
cmp [wmsg], WM_CREATE
je _crear
cmp [wmsg], WM_PAINT
je _pintar
cmp [wmsg], WM_KEYDOWN
je _tecla
cmp [wmsg], WM_LBUTTONDOWN
je _mouse_click
cmp [wmsg], WM_DESTROY
je _destruye
_defecto:
invoke DefWindowProc, [hwnd], [wmsg], [wparam], [lparam]
jmp _final
_crear:
;Aquí vendria la carga de los gráficos
mov [hMuralla_ED], eax
mov [Posx], 750d
mov [Posy], 2d
mov [Posy2], 45d
mov [Posy3], 88d
mov [Posy4], 131d
mov [Posy5], 174d
mov [cPosx1], 749d
mov [cPosy1], 1d
mov [cPosx2], 790d
mov [cPosy2], 43d
jmp _final
_mouse_click:
invoke GetCursorPos, punto
mov eax, [cPosx1]
cmp [punto.x], eax
jl _final
mov eax, [cPosx2]
cmp [punto.x], eax
ja _final
mov eax, [cPosy1]
cmp [punto.y], eax
jl _final
mov eax, [cPosy2]
cmp [punto.y], eax
ja _final
invoke InvalidateRect, [hwnd], NULL, TRUE
jmp _final
_tecla:
cmp [wparam], VK_DOWN
jne .otra
cmp [cPosy1], 0ADh ;Mira si es el último recuadro y si lo es no sigue sumando
je _final
add [cPosy1], 43d
add [cPosy2], 43d
jmp .pintando
.otra:
cmp [wparam], VK_UP
jne _final
cmp [cPosy1], 1d
je _final
sub [cPosy1], 43d
sub [cPosy2], 43d
.pintando:
invoke InvalidateRect, [hwnd], NULL, TRUE
jmp _final
_pintar:
invoke BeginPaint, [hwnd], ps
mov [hdc], eax
invoke CreateCompatibleDC, [hdc]
mov [hMemDC], eax
invoke GetClientRect, [hwnd], rect
;Aquí vendrían los gráficos
stdcall Dibuja_Lineas, [cPosx1], [cPosx2], [cPosy1], [cPosy2],0000FF00h
invoke DeleteDC, [hMemDC]
invoke EndPaint, [hwnd], ps
jmp _final
_destruye:
invoke PostQuitMessage, 0
_final:
ret
endp
proc Dibuja_Lineas uses ebx esi edi, posicionx1, posicionx2, posiciony1, posiciony2, color
invoke CreatePen, PS_SOLID, 1, [color]
mov [hPen], eax
invoke SelectObject, [hdc], [hPen]
mov [hPenOld], eax
invoke MoveToEx, [ps.hdc], [posicionx1], [posiciony1], 0
invoke LineTo, [ps.hdc], [posicionx2], [posiciony1]
invoke LineTo, [ps.hdc], [posicionx2], [posiciony2]
invoke LineTo, [ps.hdc], [posicionx1], [posiciony2]
invoke LineTo, [ps.hdc], [posicionx1], [posiciony1]
ret
endp
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Sección de datos importación ++
;++++++++++++++++++++++++++++++++++++++++++++++++
section '.idata' import data readable
library kernel32, 'kernel32.dll',\
user32, 'user32.dll',\
gdi32, 'gdi32.dll'
include 'api\kernel32.inc'
include 'api\user32.inc'
include 'api\gdi32.inc'
;++++++++++++++++++++++++++++++++++++++++++++++++
;++ Sección de recursos ++
;++++++++++++++++++++++++++++++++++++++++++++++++
;Aquí vendrían los gráficos
Puedes usar las teclas del cursor ARRIBA y ABAJO, para mover el area. Se que aunque funcionase no haría nada, pero eso es porque al no funcionar no lo he echo :huh:
la posicion del raton se guarda en el paramentro lParam.
X se encuentra en low word de lparam.
Y se encuentra en high word de lparam.
Lo que tienes que hacer en el evento WM_LBUTTONDOWN es
mov eax,[lparam]
and eax, 0xFFFF
mov [XPos],eax
mov eax,[lparam]
shr eax,16
mov [YPos],eax
referencia mas detallada en los tutoriales de Iczelion
http://win32assembly.online.fr/tut7.html
Me imaginaba esa contestación. Conocía lo del lparam y comprendo el código que has usado; lo miraré a ver si así va mejor.
Use el GetCursorPos por comodidad, pues se supone que te da las coordenadas del cursor de todas formas.
Si el problema no esta allí, hecha un vistazo a ClientToScreen.
http://msdn.microsoft.com/en-us/library/aa931003.aspx
Depura el programa. haz click en la esquina superior izquierda, y la esquina inferior derecha. Compara los valores. Si no son los que deberian, pues algo esta mal en como obtienes las coordendas.
Muchísimas gracias _Enko. No soy capaz de ver el problema pues realmente lo que pasa es que las coordenadas no son las que deberían.
Con el modo "normal", el que has escrito tú, funciona correctamente. Si alguien sabe el motivo, lo que hice mal, agradecería su comentario pues es así como mejor se aprende.
Gracias de nuevo _Enko
GetCursorPos
CitarRetrieves the cursor's position, in screen coordinates.
Es decir, devuelve las coordenadas del raton en relacion a la Pantalla.
Mientas que lparam en el evento del click, tiene las coordenadas en relacion a la ventana.
Ya sabia yo que tenía que ser un error de comprensión. No me di cuenta de lo de las coordenadas de pantalla / ventana. La próxima vez estaré má atento.
Gracias de nuevo ;-)