2015-09-16 3 views
-1

Я работаю над проектом в C# и должен получить координаты мыши в координатах. Щелчок можно сделать за пределами экрана. Я нашел код в Интернете, но не могу сделать координаты в текстовом поле. Вот код. Я пытался написать «hookStruct.pt.x» в HookCallBack, но он не работал. Кто-нибудь знает, как это сделать?Как связаться с координатами мыши

namespace Mouse_Hook 
{ 
    public partial class Form1 : Form 
    { 
     public Form1() 
     { 
      InitializeComponent(); 
     } 

     [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); 

     private delegate IntPtr LowLevelMouseProc(int nCode, IntPtr wParam, IntPtr lParam); 
     private static LowLevelMouseProc _proc = HookCallback; 

     private const int WH_MOUSE_LL = 14; 
     private static IntPtr _hookID = IntPtr.Zero; 

     private static IntPtr HookCallback(
     int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && 
      MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) 
      { 

       MSLLHOOKSTRUCT hookStruct = (MSLLHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(MSLLHOOKSTRUCT)); 
       Console.WriteLine(hookStruct.pt.x + ", " + hookStruct.pt.y); 
       Console.Read(); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 

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

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

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

     private enum MouseMessages 
     { 
      WM_LBUTTONDOWN = 0x0201, 
      WM_LBUTTONUP = 0x0202, 
      WM_MOUSEMOVE = 0x0200, 
      WM_MOUSEWHEEL = 0x020A, 
      WM_RBUTTONDOWN = 0x0204, 
      WM_RBUTTONUP = 0x0205 
     } 

     private void Form1_Load(object sender, EventArgs e) 
     { 
      _hookID = SetHook(_proc); 
      Application.Run(); 
      UnhookWindowsHookEx(_hookID); 
     } 

    } 
} 
+0

Что действительно «не сработало»? За исключением странного 'Application.Run' внутри загрузки формы и' Console' вызовы из WF-приложения. –

+0

Я хочу установить «textbox1.Text = hookStruct.pt.x» вместо Console.Writeline, но нет текстового поля 1, только класс TextBox –

+1

Поиск TextBox от метода * static * обычно является отказом кита. Вам нужна ссылка, у вас ее нет. Очень простой способ - просто не сделать его статическим, но членом экземпляра любого окна или формы, который содержит текстовое поле. Лучше всего изучать ООП, прежде чем пытаться взломать крючки. –

ответ

0

Если я правильно понимаю, лучше всего подходит для ваших нужд будет поставить функциональность крюк внутри статического (глобального) класса и выставить статический случай. В вашем случае форма будет подписана на это событие при открытии (и должна быть отменена при закрытии). Что-то вроде этого

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

namespace Samples 
{ 
    public static class MouseHook 
    { 
     [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); 

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

     private const int WH_MOUSE_LL = 14; 

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

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

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

     private enum MouseMessages 
     { 
      WM_LBUTTONDOWN = 0x0201, 
      WM_LBUTTONUP = 0x0202, 
      WM_MOUSEMOVE = 0x0200, 
      WM_MOUSEWHEEL = 0x020A, 
      WM_RBUTTONDOWN = 0x0204, 
      WM_RBUTTONUP = 0x0205 
     } 

     private static IntPtr _hookID = IntPtr.Zero; 

     public static void Register() 
     { 
      if (_hookID != IntPtr.Zero) return; 
      _hookID = SetHook(HookCallback); 
     } 

     public static void Unregister() 
     { 
      if (_hookID == IntPtr.Zero) return; 
      UnhookWindowsHookEx(_hookID); 
      _hookID = IntPtr.Zero; 
     } 

     private static IntPtr HookCallback(int nCode, IntPtr wParam, IntPtr lParam) 
     { 
      if (nCode >= 0 && MouseMessages.WM_LBUTTONDOWN == (MouseMessages)wParam) 
      { 
       var handler = LButtonDown; 
       if (handler != null) handler(null, EventArgs.Empty); 
      } 
      return CallNextHookEx(_hookID, nCode, wParam, lParam); 
     } 

     public static event EventHandler LButtonDown; 
    } 
    // Test 
    class TestForm : Form 
    { 
     Label label; 
     protected override void OnLoad(EventArgs e) 
     { 
      Controls.Add(label = new Label()); 
      MouseHook.LButtonDown += OnHookLButtonDown; 
      base.OnLoad(e); 
     } 
     protected override void OnFormClosed(FormClosedEventArgs e) 
     { 
      MouseHook.LButtonDown -= OnHookLButtonDown; 
     } 
     private void OnHookLButtonDown(object sender, EventArgs e) 
     { 
      var pt = Control.MousePosition; 
      label.Text = "{" + pt.X + ", " + pt.Y + "}"; 
     } 
    } 
    static class Program 
    { 
     [STAThread] 
     static void Main() 
     { 
      Application.EnableVisualStyles(); 
      Application.SetCompatibleTextRenderingDefault(false); 
      MouseHook.Register(); 
      try { Application.Run(new TestForm()); } 
      finally { MouseHook.Unregister(); } 
     } 
    } 
} 

Обратите внимание, что это всего лишь пример. Производственный код будет извлекать информацию из параметров крючка и выставлять глобальные события, подобные стандарту MoseMove, MouseDown и т. Д.

Смежные вопросы