posición del ratón

Iniciado por hosuko, 8 Julio 2011, 18:46 PM

0 Miembros y 1 Visitante están viendo este tema.

hosuko

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:

_Enko

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

hosuko

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.

_Enko

#3
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.


hosuko

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

_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.

hosuko

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  ;-)