2012-01-15 79 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