我正在使用c#中的项目,需要在文本框中获取鼠标点击坐标。可以在屏幕外单击。我在互联网上找到了一个代码,但无法在文本框中显示坐标。这是代码..我试图在HookCallBack中编写“hookStruct.pt.x”,但它不能正常工作。有谁知道如何做到这一点?
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 :(得分: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
等的全局事件。