Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何捕获鼠标移动事件_C#_Winforms - Fatal编程技术网

C# 如何捕获鼠标移动事件

C# 如何捕获鼠标移动事件,c#,winforms,C#,Winforms,我想在我的主窗体中捕获鼠标移动事件。尽管我能够连接主窗体的MouseEventHandler,但当光标位于UserControl或任何其他控件上时,事件不再触发。如何确保我始终处于鼠标位置。您可以使用低级鼠标挂钩。请参阅示例并检查HookCallback中的WM_MOUSEMOVE mesage 您还可以使用IMessageFilter类捕获鼠标事件并触发事件以获取位置(注意:这将仅获取窗口上的位置,而不是窗口外的位置): 这是解决办法。虽然我可以看到另一个类似的答案。但既然是我写的,我想把它贴

我想在我的主窗体中捕获鼠标移动事件。尽管我能够连接主窗体的
MouseEventHandler
,但当光标位于UserControl或任何其他控件上时,事件不再触发。如何确保我始终处于鼠标位置。

您可以使用低级鼠标挂钩。请参阅示例并检查HookCallback中的WM_MOUSEMOVE mesage

您还可以使用IMessageFilter类捕获鼠标事件并触发事件以获取位置(注意:这将仅获取窗口上的位置,而不是窗口外的位置):


这是解决办法。虽然我可以看到另一个类似的答案。但既然是我写的,我想把它贴出来。这里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;
    }
}

我尝试了@SwDevMan81提供的上述解决方案。尽管它工作得很好,但我也有@Randy Gamage提到的问题,“即使鼠标不移动,MouseMoved函数也会不断被调用。当鼠标不在应用程序上方时,它会停止启动”。 无论如何,这就是我想到的:

以构造器的形式:

GlobalMouseHandler.MouseMovedEvent += GlobalMouseHandler_MouseMovedEvent;
Application.AddMessageFilter(new GlobalMouseHandler());

InitializeComponent();
事件处理程序:

private void GlobalMouseHandler_MouseMovedEvent(object sender, MouseEventArgs e)
{
   try
   {
      //Do whatever ...
   }
   catch { }
}
我的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
}
公共类GlobalMouseHandler:IMessageFilter { 私有常量int WM_MOUSEMOVE=0x0200; private System.Drawing.Point previousMousePosition=新系统.Drawing.Point(); public static event EventHandler MouseMovedEvent=委托{}; #区域IMessageFilter成员 公共bool预过滤器消息(参考System.Windows.Forms.Message m) { if(m.Msg==WM_MOUSEMOVE) { System.Drawing.Point currentMousePoint=Control.MousePosition; if(上一个mouseposition!=当前mousepoint) { previousMousePosition=当前鼠标点; MouseMovedEvent(这个,新的MouseEventArgs(MouseButtons.None,0,currentMousePoint.X,currentMousePoint.Y,0)); } } //始终允许消息继续到下一个筛选器控件 返回false; } #端区 }
我希望有人能使用它。

这里有一个解决方案,用于WPF,在整个应用程序上使用全局鼠标处理程序。由于WPF中的其他鼠标问题,我也使用了此选项

using 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;
}

按照dup线程中的说明使用IMessageFilter。这非常有效,谢谢。我使用了你在这里发布的来源。然而,我注意到,MouseMoved函数不断被调用,即使鼠标没有移动。当鼠标不在应用程序上时,它停止启动。@SwDevMan81人们如何找到在哪里查找消息id的HEXCODE?我看到所有这些导入调用都带有user32dll调用,我真的很想知道在哪里可以找到有关这些调用的信息this@AndreasMüller-和@SwDevMan81正如randy所说,即使鼠标没有移动,它仍在不断调用函数,我测试了它出了什么问题?在我的简单应用程序中,这只在鼠标在窗口内移动时起作用,也许它需要更高的权限才能从其他进程捕获mouseevent?Win10 x64仅当wm_mousemove发送到应用程序(即当其窗口处于活动状态或鼠标光标下时)时,此功能才有效。如果只对单个窗体感兴趣,则需要检查该窗体是否处于活动状态。顺便说一句,当其他窗口也处于活动状态时,它会触发。在应用程序运行之前,您不必添加过滤器。我明白了为什么它会调用该方法两次,因为当第一次触发事件时,
previousMousePosition
的值为
x=0;y=0
当程序跳转到
if(previousMousePosition!=currentMousePosition)
返回true时,我只添加一个条件,检查
previousMousePosition
是否有默认值,并在
if
语句之前退出函数。这就解决了问题
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
}
using 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;
}