2012-01-15 78 views
4

我知道如何从MSDN上的示例修改光标位置。如何跟踪鼠标X/Y位置并将其打印到标签?

我的问题是如何检查鼠标移动时的位置,然后打印X和Y位置来表示标签?

编辑:可以说我想从我的整个屏幕上跟踪我的鼠标位置。编辑2:我的应用程序将在后台/最小化。

我已经使用鼠标钩子:

namespace Program 
{ 
    public partial class MouseHook 
    { 
     [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)] 
     private static extern void mouse_event(int dwFlags, int dx, int dy, int dwData, IntPtr dwExtraInfo); 

     private const int MOUSEEVENTF_LEFTDOWN = 0x02; 
     private const int MOUSEEVENTF_LEFTUP = 0x04; 
     private const int MOUSEEVENTF_RIGHTDOWN = 0x08; 
     private const int MOUSEEVENTF_RIGHTUP = 0x10; 

     public void DoMouseClick() 
     { 
      int X = Cursor.Position.X; 
      int Y = Cursor.Position.Y; 

      IntPtr newP = new IntPtr(Convert.ToInt64("0", 16)); 
      mouse_event(MOUSEEVENTF_LEFTDOWN | MOUSEEVENTF_LEFTUP, X, Y, 0, newP); 
     } 
    } 
} 
+4

这已问过很多次了。在搜索框中输入“+ setwindowshookex + wh_mouse_ll”。或者只是使用50毫秒的定时器和光标。位置 – 2012-01-15 17:38:23

+0

@Hans Passant,定时器解决方案似乎是检查x/y位置最简单的方法。我只需要弄清楚如何检查现在的位置。 +1为此:) – HelpNeeder 2012-01-15 17:41:09

+0

@Cody Gray,如果问题在注释答案前3年发布,这个问题如何重复? – HelpNeeder 2017-04-30 18:32:59

回答

3

Here是系统级别鼠标事件处理调用(低级别鼠标处理程序)的msdn文档。

Here是使用低级别鼠标特效更改滚动事件的示例。

在第二个链接的答案中使用here中的WM_MOUSEMOVE而不是WM_MOUSEWHEEL。

有一点需要注意:当该程序在鼠标悬停在具有提升特权的程序上时继续捕获鼠标事件时,该程序必须以提升的特权启动。

代码(未测试):

using System; 

using System.Diagnostics; 
using System.Windows.Forms; 
using System.Runtime.InteropServices; 

namespace CatchMouseMove 
{ 
    class InterceptMouse 
    { 
     const int INPUT_MOUSE = 0; 
     const int MOUSEEVENTF_WHEEL = 0x0800; 
     const int WH_MOUSE_LL = 14; 


     private static LowLevelMouseProc _proc = HookCallback; 
     private static IntPtr _hookID = IntPtr.Zero; 

     public static void Main() 
     { 
      _hookID = SetHook(_proc); 

      if (_hookID == null) 
      { 
       MessageBox.Show("SetWindowsHookEx Failed"); 
       return; 
      } 
      Application.Run(); 
      UnhookWindowsHookEx(_hookID); 
     } 

     private static IntPtr SetHook(LowLevelMouseProc proc) 
     { 
      using (Process curProcess = Process.GetCurrentProcess()) 
      using (ProcessModule curModule = curProcess.MainModule) 
      { 
       return SetWindowsHookEx(WH_MOUSE_LL, proc, 
        GetModuleHandle(curModule.ModuleName), 0); 
      } 
     } 

     private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 

     private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      int xPos = 0; 
      int yPos = 0; 

      if (nCode >= 0 && MouseMessages.WM_MOUSEMOVE == (MouseMessages)wParam) 
      {  
       xPos = GET_X_LPARAM(lParam); 
       yPos = GET_Y_LPARAM(lParam); 

       //do stuff with xPos and yPos 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 


     private enum MouseMessages 
     { 
      WM_MOUSEMOVE = 0x0200 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct POINT 
     { 
      public int x; 
      public int y; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     private struct MSLLHOOKSTRUCT 
     { 
      public POINT pt; 
      public int mouseData; 
      public int flags; 
      public int time; 
      public IntPtr dwExtraInfo; 
     } 

     public struct INPUT 
     { 
      public int type; 
      public MOUSEINPUT mi; 
     } 

     [StructLayout(LayoutKind.Sequential)] 
     public struct MOUSEINPUT 
     { 
      public int dx; 
      public int dy; 
      public int mouseData; 
      public uint dwFlags; 
      public int time; 
      public int dwExtraInfo; 
     } 



     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr SetWindowsHookEx(int idHook, 
      LowLevelMouseProc lpfn, IntPtr hMod, uint dwThreadId); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     [return: MarshalAs(UnmanagedType.Bool)] 
     private static extern bool UnhookWindowsHookEx(IntPtr hhk); 

     [DllImport("user32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr CallNextHookEx(IntPtr hhk, int nCode, 
      IntPtr wParam, IntPtr lParam); 

     [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] 
     private static extern IntPtr GetModuleHandle(string lpModuleName); 

    } 

} 
2

您可以使用MouseMove event的EventArgs的,因为它拥有鼠标坐标。从那里你可以很容易地将标签的文本属性设置为从e(MouseMove EventArgs)获取的X或Y坐标。

private void Form_MouseMove(object sender, MouseEventArgs e) 
{ 
    // Update the mouse coordinates displayed in the textbox. 
    myTextBox.Text = e.Location.ToString(); 
} 
+0

好吧,我明白了。但是,因为我必须有一个对象来执行处理程序,例如:'textBox1.TextChanged + = new EventArgs(textBox1_TextChanged);'我会调用哪个对象? – HelpNeeder 2012-01-15 16:53:34

+1

@帮助:'TextChanged'是错误的事件。你想处理'MouseMove'事件。在该事件处理程序方法的内部,更新您的文本框:'textBox1.Text = e.Location.ToString();' – 2012-01-15 16:56:22

+0

@Cody Gray,我知道。但我的问题是我会引用什么对象,这意味着我会用textBox1替代? – HelpNeeder 2012-01-15 16:58:06

3

您需要设置Windows钩子,以实现这一目标。 MSDN文章How to set a Windows hook in Visual C# .NET显示了如何设置鼠标钩子。

我试过了,即使当鼠标光标在控件上时,它也会捕捉鼠标遍布窗体。

+0

这个例子很好,除了它是为一个独立的线程设置的,它可以找到你的表单而不是直接绑定到表单。 – mydogisbox 2012-01-15 18:21:18

+0

是的,但很容易适应。 – 2012-01-15 18:58:06