C# 如何捕获鼠标移动事件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2063974/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I capture the mouse move event
提问by fishhead
I would like to capture the mouse move event in my main form. Although I am able to wire up the MouseEventHandler
for the main form, the event no longer fires when the cursor is over a UserControl or any other control. How do I ensure that I always have the mouse position.
我想在我的主窗体中捕获鼠标移动事件。尽管我能够MouseEventHandler
为主窗体连接,但当光标位于 UserControl 或任何其他控件上时,该事件不再触发。我如何确保我始终拥有鼠标位置。
采纳答案by SwDevMan81
You could use a low level mouse hook. See thisexample and check for the WM_MOUSEMOVE mesage in HookCallback.
您可以使用低级鼠标挂钩。请参阅此示例并检查 HookCallback 中的 WM_MOUSEMOVE 消息。
You could also use the IMessageFilter class to catch the Mouse Events and trigger an event to get the position (note: this will only get the position over the window, not outside of it):
您还可以使用 IMessageFilter 类来捕获鼠标事件并触发事件以获取位置(注意:这只会获取窗口上方的位置,而不是窗口之外的位置):
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
}
}
回答by particle
Here is the solution. Although I can see another answer with a similar approach. But since I wrote it I want to post it. Here MouseMessageFilter has a static event call MouseMove which you can subscribe from anywhere within the application.
这是解决方案。虽然我可以用类似的方法看到另一个答案。但既然写了,就想发一下。这里 MouseMessageFilter 有一个静态事件调用 MouseMove,您可以从应用程序内的任何地方订阅它。
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;
}
}
回答by Belmiris
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);
}
}
}
回答by Viking
I tried the above mentioned solutoution provided by @SwDevMan81. Although it worked nicely, I also had the issue @Randy Gamage mentioned "that the MouseMoved function gets called continuously, even though the mouse is not moving. It stops firing when the mouse is not over the application". In any case this is what I came up with:
我尝试了@SwDevMan81 提供的上述解决方案。虽然它工作得很好,但我也遇到了@Randy Gamage 提到的问题“即使鼠标没有移动,MouseMoved 函数也会被连续调用。当鼠标不在应用程序上时它会停止触发”。无论如何,这就是我想出的:
In the form constructor:
在表单构造函数中:
GlobalMouseHandler.MouseMovedEvent += GlobalMouseHandler_MouseMovedEvent;
Application.AddMessageFilter(new GlobalMouseHandler());
InitializeComponent();
The event handler:
事件处理程序:
private void GlobalMouseHandler_MouseMovedEvent(object sender, MouseEventArgs e)
{
try
{
//Do whatever ...
}
catch { }
}
And my slightly altered GlobalMouseHandler class:
我稍微改变了 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
}
I hope somebody can use it.
我希望有人可以使用它。
回答by marsh-wiggle
Here is a solution for WPF with a global mouse handler over the whole application. I use this also due to other mouse issues in WPF.
这是 WPF 的解决方案,在整个应用程序上具有全局鼠标处理程序。由于 WPF 中的其他鼠标问题,我也使用它。
using System.Windows.Interop;
使用 System.Windows.Interop;
private const int WM_MOUSEMOVE = 0x0200;
public delegate void Del_MouseMovedEvent(Point mousePosition);
// Relative to this control, the mouse position will calculated
public IInputElement Elmt_MouseMovedRelativeElement = null;
// !! This is static; needs special treatment in a multithreaded application !!
public static event Del_MouseMovedEvent Evt_TheMouseMoved = null;
// your main function call
public MyMainWindows()
{
// install the windows message filter first
ComponentDispatcher.ThreadFilterMessage += ComponentDispatcher_ThreadFilterMessage;
InitializeComponent();
...
}
// filtering the windows messages
private void ComponentDispatcher_ThreadFilterMessage(ref MSG msg, ref bool handled)
{
if(msg.message == WM_MOUSEMOVE)
{
this.Evt_TheMouseMoved?.Invoke(Mouse.GetPosition(this.Elmt_MouseMovedRelativeElement));
}
}
// individual event for mouse movement
private void MyMouseMove(Point mousePoint)
{
// called on every mouse move when event is assigned
Console.WriteLine(mousePoint.X + " " + mousePoint.Y);
}
private void AnyFunctionDeeperInTheCode()
{
// assign the handler to the static var of the main window
MyMainWindows.Evt_TheMouseMoved += MyMouseMove;
// set the element / control to which the mouse position should be calculated;
MyMainWindows.Elmt_MouseMovedRelativeElement = this;
...
// undassign the handler from the static var of the main window
MyMainWindows.Evt_TheMouseMoved -= MyMouseMove;
}