Me gustaría capturar el evento de mover el mouse en mi formulario principal. Aunque puedo conectar el MouseEventHandler
para el formulario principal, el evento ya no se dispara cuando el cursor está sobre un UserControl o cualquier otro control. ¿Cómo me aseguro de que siempre tenga la posición del mouse?Cómo capturo el evento de mover el mouse
Respuesta
Puede usar un gancho de mouse de bajo nivel. Vea el ejemplo this y busque el mensaje WM_MOUSEMOVE en HookCallback.
También se puede utilizar la clase IMessageFilter para atrapar a los eventos de ratón y desencadenar un evento para obtener la posición (nota: esto sólo se conseguirá la posición sobre la ventana, no fuera de él):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
namespace GlobalMouseEvents
{
public partial class Form1 : Form
{
public Form1()
{
GlobalMouseHandler gmh = new GlobalMouseHandler();
gmh.TheMouseMoved += new MouseMovedEvent(gmh_TheMouseMoved);
Application.AddMessageFilter(gmh);
InitializeComponent();
}
void gmh_TheMouseMoved()
{
Point cur_pos = System.Windows.Forms.Cursor.Position;
System.Console.WriteLine(cur_pos);
}
}
public delegate void MouseMovedEvent();
public class GlobalMouseHandler : IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
public event MouseMovedEvent TheMouseMoved;
#region IMessageFilter Members
public bool PreFilterMessage(ref Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
if (TheMouseMoved != null)
{
TheMouseMoved();
}
}
// Always allow message to continue to the next filter control
return false;
}
#endregion
}
}
Esto funciona genial, gracias. Usé la fuente que publicaste aquí. Sin embargo, me di cuenta de que la función MouseMoved se llama continuamente, incluso aunque el mouse no se mueva. Deja de disparar cuando el mouse no está sobre la aplicación. –
@ SwDevMan81 ¿Cómo averigua la gente dónde buscar los códigos hexadecimales para identificar los mensajes? Veo todas esas llamadas Import con llamadas a User32 dll y realmente me pregunto dónde encontrar información sobre este – Dbl
@ AndreasMüller - [Notificaciones de teclado] (http://msdn.microsoft.com/en-us/library/windows/desktop/ ff468861 (v = vs.85) .aspx) y [Notificaciones de mouse] (http://msdn.microsoft.com/en-us/library/windows/desktop/ff468877 (v = vs.85) .aspx) – SwDevMan81
Aquí está la solución. Aunque puedo ver otra respuesta con un enfoque similar. Pero desde que lo escribí quiero publicarlo. Aquí MouseMessageFilter tiene un evento estático llamada MouseMove que puede suscribirse desde cualquier lugar dentro de la aplicación.
static class Program
{
[STAThread]
static void Main() {
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.AddMessageFilter(new MouseMessageFilter());
MouseMessageFilter.MouseMove += new MouseEventHandler(OnGlobalMouseMove);
Application.Run(new MainForm());
}
static void OnGlobalMouseMove(object sender, MouseEventArgs e) {
Console.WriteLine(e.Location.ToString());
}
}
class MouseMessageFilter : IMessageFilter
{
public static event MouseEventHandler MouseMove = delegate { };
const int WM_MOUSEMOVE = 0x0200;
public bool PreFilterMessage(ref Message m) {
if (m.Msg == WM_MOUSEMOVE) {
Point mousePosition = Control.MousePosition;
MouseMove(null, new MouseEventArgs(
MouseButtons.None, 0, mousePosition.X, mousePosition.Y,0));
}
return false;
}
}
esto solo funciona si wm_mousemove se envía a su aplicación (que es cuando uno de sus ventana está activa o está debajo del cursor del mouse) si solo está interesado en una sola forma, entonces necesita verificar si esa forma está activa. .btw se dispara cuando otras ventanas están activas también. y no tienes que agregar tu filtro antes de ejecutar la aplicación. – TakeMeAsAGuest
public partial class frmCaptureMouse : Form
{
[DllImport("user32.dll")]
static extern IntPtr SetCapture(IntPtr hWnd);
public frmCaptureMouse()
{
InitializeComponent();
}
private void frmCaptureMouse_MouseMove(object sender, MouseEventArgs e)
{
try
{
lblCoords.Text = e.Location.X.ToString() + ", " + e.Location.Y.ToString();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnCapture_Click(object sender, EventArgs e)
{
try
{
SetCapture(this.Handle);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
Probé la solutoution mencionada proporcionada por @ SwDevMan81. Aunque funcionó bien, también tuve el problema @Randy Gamage mencionó "que la función MouseMoved se llama continuamente, aunque el mouse no se mueva. Deja de disparar cuando el mouse no está sobre la aplicación". En cualquier caso, esto es lo que ocurrió:
En la forma constructor:
GlobalMouseHandler.MouseMovedEvent += GlobalMouseHandler_MouseMovedEvent;
Application.AddMessageFilter(new GlobalMouseHandler());
InitializeComponent();
El controlador de eventos:
private void GlobalMouseHandler_MouseMovedEvent(object sender, MouseEventArgs e)
{
try
{
//Do whatever ...
}
catch { }
}
Y mi ligeramente alterada clase GlobalMouseHandler:
public class GlobalMouseHandler : IMessageFilter
{
private const int WM_MOUSEMOVE = 0x0200;
private System.Drawing.Point previousMousePosition = new System.Drawing.Point();
public static event EventHandler<MouseEventArgs> MouseMovedEvent = delegate { };
#region IMessageFilter Members
public bool PreFilterMessage(ref System.Windows.Forms.Message m)
{
if (m.Msg == WM_MOUSEMOVE)
{
System.Drawing.Point currentMousePoint = Control.MousePosition;
if (previousMousePosition != currentMousePoint)
{
previousMousePosition = currentMousePoint;
MouseMovedEvent(this, new MouseEventArgs(MouseButtons.None, 0, currentMousePoint.X, currentMousePoint.Y, 0));
}
}
// Always allow message to continue to the next filter control
return false;
}
#endregion
}
Espero que alguien pueda usarlo.
Esto tiene una buena respuesta pero llama al método dos veces –
Me explico por qué llama al método dos veces porque cuando el evento se disparó por primera vez 'previousMousePosition' tiene un valor de' x = 0; y = 0' y cuando el programa saltar a 'if (previousMousePosition!= currentMousePoint) 'devuelve verdadero, solo agrego una condición que verificará si' previousMousePosition' tiene un valor predeterminado y saldrá de la función antes de la instrucción 'if'. Esto resuelve el problema –
- 1. Mover el mouse
- 2. Mover el mouse mediante programación
- 3. no se puede obtener el evento de mover el mouse de/dev/input/event *
- 4. java mover componentes con el mouse
- 5. Cómo mover (o hacer cualquier cosa con) el mouse
- 6. Mover el puntero del mouse en JavaScript
- 7. Hacer clic y mover el mouse mediante programación con VB.NET
- 8. Cómo mover div con el mouse usando jquery?
- 9. ¿Cómo mover el cursor del mouse usando C#?
- 10. Cómo detectar el estado presionada de la tecla Mayús al mover el mouse
- 11. Evento Delphi Mouse wheel en el componente
- 12. Mover la imagen del enlace 5px al pasar el mouse
- 13. SetCursor revierte después de mover un mouse
- 14. QML: ¿cómo manejar el mouse?
- 15. Evento GTK # mouse en el área de dibujo
- 16. ¿Cómo hacer que el cursor del mouse agarre el mouse?
- 17. Error de Chrome? El cursor cambia con el mouse hacia abajo + mover
- 18. Obteniendo la posición del mouse en el evento del teclado
- 19. HTML5 Canvas Mouse Wheel Evento
- 20. ¿Cómo capturo el STDOUT de Perl en una variable?
- 21. C# moviendo el mouse de forma realista
- 22. El elemento activo Mover pierde el evento mouseout en Internet Explorer
- 23. Mover el mouse de Java en cualquier lugar de la pantalla
- 24. ¿En evento de mouse en WPF?
- 25. Evento de rueda de mouse 'ficticio' desencadenante
- 26. Evento de mouse movido dentro de JPanel
- 27. Perder al pasar el ratón al animar con jQuery (sin mover el mouse)
- 28. jQuery opción de autocompletar el mouse activa el evento de desenfoque
- 29. ¿Cómo capturo el resultado PHP en una variable?
- 30. Evento de mouse en fondo transparente
Use IMessageFilter como se explica en el subproceso dúplex. –