Tuesday, 1 September 2009

Implementación de un Canvas para modificar Objetos en Delphi parte IV

En ésta IV parte os mostraré el problema que tiene el trabajar con los eventos del mouse sobre un componente gráfico ya sea TImage o TPaintBox o cualquiera que disponga de Canvas y eventos de mouse. Las acciones del mouse tienen un pequeño problema y es que funcionan mediante eventos. Por lo tanto ésto significa que mientras movemos uno de los objetos con el mouse, si vamos demasiado rápido, éste se nos puede escapar. Y aquí tenemos nuestro primer problema a la hora de desarrollar un canvas para la modificación de objetos. Existen varias técnicas para que ésto no ocurra o para que quede un poco más disimulado. Todo depende de que componente utilizamos y la manera en que lo utilizamos.

Hay que tener amplios conocimientos de como funcionan los mensajes y como gestionan los diversos componentes el refresco de los gráficos mediante los métodos .refresh o .invalidate. Si os fijáis en la jerarquía de clases de los elementos que contienen eventos de mouse (OnDragDrop, OnDragOver, OnEndDock, OnEndDrag, OnMouseActivate, OnMouseDown, OnMouseEnter, OnMouseLeave, OnMouseMove, OnMouseUp, OnStartDock, OnStartDrag, etc.) como TShape, TPaintBox, TImage, TBevel, etc, heredan de la clase TGraphicControl. Os recomiendo pasar por la unit ExtCtrls y observar el código de los diferentes componentes. De ahí podréis sacar bastantes ideas de como se utilizan los eventos y los mensajes.

Si cogéis la penúltima versión de Thundaxboxmanager v1.0.0 build 9.exe, podréis comprobar el tema que os comento sobre la velocidad del mouse:

Cómo podéis ver en la imagen, he desplazado el mouse muy rápido, y aunque la caja está seleccionada, no se ha desplazado con el mouse. Ésto pasa ya que los mensajes del mouse se hacen cada x tiempo, por lo tanto el código que hay en el evento (OnMouseMove) solo se llama ciertas veces. Éste problema lo genera el propio windows. Windows no acumula los mensajes del mouse en la cola de mensajes, en vez de eso lo que hace es reemplazar el último de los mensajes. Por lo tanto puede ser que el último mensaje enviado esté fuera del alcance de la caja y por eso sale de sus margenes y no es desplazado.

Aquí los trucos que podemos utilizar son los mismos que se trabajan con la creación de vídeo juegos. Lo que tenemos que hacer es ir capturando éstos mensajes lo más rápido posible y procesarlos (hay muchas técnicas para ésto). Podemos sacar ideas observando los métodos invalidate o refresh de TControl en la unit Controls. Para que quede un movimiento suave, podemos ir redibujando las zonas afectadas por el movimiento, e incluso hacer que el objeto siga el mouse y no al revés.

Si os descargáis la versión thundaxBoxManager v1.0.0 build 10.exe veréis que ahora la caja no se suelta del mouse por más rápido que lo movamos.

Es una versión en desarrollo, y puede ser que alguna de las funcionalidades de la versión anterior no estén disponibles. En ésta he modificado el comportamiento de los mensajes y ahora voy donde va el mouse, ya que es normal que se pierdan mensajes.

  • Enlaces de interés:
Handling Mouse messages.
Capture mouse event inside TImage.
Catching all mouse events.
Hooking mouse movement.
WM_PRINT Message.
Screen Grab Utility.
Hoot Keys delphi.
How to hook the mouse.
Understanding Drag Drop operations.

0 comments:

Post a Comment