У меня есть небольшое настольное приложение, в котором я использую мышиный крюк для отслеживания события щелчка мыши внутри и вне формы окна.Поэтому я хочу, чтобы пользовательский элемент управления вызывал событие при каждом щелчке мыши по этому элементу управления, но когда щелкнул сам элемент управления или щелкнули дочерние элементы управления в этом пользовательском элементе управления, я хочу игнорировать событие или действовать иначе.
Проблема в том, что все найденные мной крючки для мыши не имеют возможности узнать окно управления, которое вот-вот получит событие щелчка.
Мне нужно заранее знать, какое окно элемента управления должно получить событие click, чтобы я мог различить, является ли он дочерним элементом пользовательского элемента управления или любым другим элементом управления или вне формы.
Вот класс мышеловка, который я использую.Я нашел это онлайн.
using System;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Threading;
using Microsoft;
namespace library
{
/// <summary>
/// Abstract base class for Mouse and Keyboard hooks
/// </summary>
public abstract class GlobalHook
{
/// <summary>
///
/// </summary>
#region Windows API Code
[StructLayout(LayoutKind.Sequential)]
protected class POINT
{
public int x;
public int y;
}
[StructLayout(LayoutKind.Sequential)]
protected class MouseHookStruct
{
public POINT pt;
public int hwnd;
public int wHitTestCode;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
protected class MouseLLHookStruct
{
public POINT pt;
public int mouseData;
public int flags;
public int time;
public int dwExtraInfo;
}
[StructLayout(LayoutKind.Sequential)]
protected class KeyboardHookStruct
{
public int vkCode;
public int scanCode;
public int flags;
public int time;
public int dwExtraInfo;
}
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
protected static extern int SetWindowsHookEx(
int idHook,
HookProc lpfn,
IntPtr hMod,
int dwThreadId);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall, SetLastError = true)]
protected static extern int UnhookWindowsHookEx(int idHook);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
protected static extern int CallNextHookEx(
int idHook,
int nCode,
IntPtr wParam,
IntPtr lParam);
[DllImport("user32")]
protected static extern int ToAscii(
int uVirtKey,
int uScanCode,
byte[] lpbKeyState,
byte[] lpwTransKey,
int fuState);
[DllImport("user32")]
protected static extern int GetKeyboardState(byte[] pbKeyState);
[DllImport("user32.dll", CharSet = CharSet.Auto,
CallingConvention = CallingConvention.StdCall)]
protected static extern short GetKeyState(int vKey);
[DllImport("user32.dll", SetLastError = true)]
static extern IntPtr GetThreadDesktop(uint dwThreadId);
protected delegate int HookProc(int nCode, IntPtr wParam, IntPtr lParam);
protected const int WH_MOUSE_LL = 14;
protected const int WH_KEYBOARD_LL = 13;
protected const int WH_MOUSE = 7;
protected const int WH_KEYBOARD = 2;
protected const int WM_MOUSEMOVE = 0x200;
protected const int WM_LBUTTONDOWN = 0x201;
protected const int WM_RBUTTONDOWN = 0x204;
protected const int WM_MBUTTONDOWN = 0x207;
protected const int WM_LBUTTONUP = 0x202;
protected const int WM_RBUTTONUP = 0x205;
protected const int WM_MBUTTONUP = 0x208;
protected const int WM_LBUTTONDBLCLK = 0x203;
protected const int WM_RBUTTONDBLCLK = 0x206;
protected const int WM_MBUTTONDBLCLK = 0x209;
protected const int WM_MOUSEWHEEL = 0x020A;
protected const int WM_KEYDOWN = 0x100;
protected const int WM_KEYUP = 0x101;
protected const int WM_SYSKEYDOWN = 0x104;
protected const int WM_SYSKEYUP = 0x105;
protected const byte VK_SHIFT = 0x10;
protected const byte VK_CAPITAL = 0x14;
protected const byte VK_NUMLOCK = 0x90;
protected const byte VK_LSHIFT = 0xA0;
protected const byte VK_RSHIFT = 0xA1;
protected const byte VK_LCONTROL = 0xA2;
protected const byte VK_RCONTROL = 0x3;
protected const byte VK_LALT = 0xA4;
protected const byte VK_RALT = 0xA5;
protected const byte LLKHF_ALTDOWN = 0x20;
#endregion
/// <summary>
///
/// </summary>
#region Private Variables
protected int _hookType;
protected int _handleToHook;
protected bool _isStarted;
protected HookProc _hookCallback;
#endregion
/// <summary>
///
/// </summary>
#region Properties
public bool IsStarted
{
///
get
{
return _isStarted;
}
}
#endregion
/// <summary>
///
/// </summary>
#region Constructor
public GlobalHook()
{
///
Application.ApplicationExit += new EventHandler(Application_ApplicationExit);
}
#endregion
/// <summary>
///
/// </summary>
#region Methods
public void Start()
{
///
if (!_isStarted && _hookType != 0)
{
// Make sure we keep a reference to this delegate!
// If not, GC randomly collects it, and a NullReference exception is thrown
_hookCallback = new HookProc(HookCallbackProcedure);
//
IntPtr pp = Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0]);
///
_handleToHook = SetWindowsHookEx(
_hookType,
_hookCallback,
(IntPtr)0/*Marshal.GetHINSTANCE(Assembly.GetExecutingAssembly().GetModules()[0])*/,
/*0*/(int)GetThreadDesktop((uint)Thread.CurrentThread.ManagedThreadId));
/// Were we able to sucessfully start hook?
if (_handleToHook != 0)
{
///
_isStarted = true;
}
}
}
public void Stop()
{
///
if (_isStarted)
{
///
UnhookWindowsHookEx(_handleToHook);
///
_isStarted = false;
}
}
protected virtual int HookCallbackProcedure(int nCode, IntPtr wParam, IntPtr lParam)
{
// This method must be overriden by each extending hook
return 0;
}
protected void Application_ApplicationExit(object sender, EventArgs e)
{
///
if (_isStarted)
{
///
Stop();
}
}
#endregion
}
/// <summary>
/// Captures global mouse events
/// </summary>
public class MouseHook : GlobalHook
{
/// <summary>
///
/// </summary>
#region MouseEventType Enum
private enum MouseEventType
{
None,
MouseDown,
MouseUp,
DoubleClick,
MouseWheel,
MouseMove
}
#endregion
/// <summary>
///
/// </summary>
#region Events
public event MouseEventHandler MouseDown;
public event MouseEventHandler MouseUp;
public event MouseEventHandler MouseMove;
public event MouseEventHandler MouseWheel;
public event EventHandler Click;
public event EventHandler DoubleClick;
#endregion
/// <summary>
///
/// </summary>
#region Constructor
public MouseHook()
{
_hookType = WH_MOUSE_LL;
}
#endregion
/// <summary>
///
/// </summary>
#region Methods
protected override int HookCallbackProcedure(int nCode, IntPtr wParam, IntPtr lParam)
{
///
if (nCode > -1 && (MouseDown != null || MouseUp != null || MouseMove != null))
{
///
MouseLLHookStruct mouseHookStruct =
(MouseLLHookStruct)Marshal.PtrToStructure(lParam, typeof(MouseLLHookStruct));
///
MouseButtons button = GetButton((Int32)wParam);
MouseEventType eventType = GetEventType((Int32)wParam);
///
MouseEventArgs e = new MouseEventArgs(
button,
(eventType == MouseEventType.DoubleClick ? 2 : 1),
mouseHookStruct.pt.x,
mouseHookStruct.pt.y,
(eventType == MouseEventType.MouseWheel ?
(short)((mouseHookStruct.mouseData >> 16) & 0xffff) : 0));
// Prevent multiple Right Click events (this probably happens for popup menus)
if (button == MouseButtons.Right && mouseHookStruct.flags != 0)
{
///
eventType = MouseEventType.None;
}
///
switch (eventType)
{
///
//Control cont = Control.FromHandle(wParam);
///
case MouseEventType.MouseDown:
///
if (MouseDown != null)
{
///
MouseDown(this, e);
}
break;
case MouseEventType.MouseUp:
if (Click != null)
{
///
Click(this, new EventArgs());
}
if (MouseUp != null)
{
///
MouseUp(this, e);
}
break;
case MouseEventType.DoubleClick:
if (DoubleClick != null)
{
///
DoubleClick(this, new EventArgs());
}
break;
case MouseEventType.MouseWheel:
if (MouseWheel != null)
{
///
MouseWheel(this, e);
}
break;
case MouseEventType.MouseMove:
if (MouseMove != null)
{
///
MouseMove(this, e);
}
break;
default:
break;
}
}
///
return CallNextHookEx(_handleToHook, nCode, wParam, lParam);
}
private MouseButtons GetButton(Int32 wParam)
{
///
switch (wParam)
{
///
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
return MouseButtons.Left;
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDBLCLK:
return MouseButtons.Right;
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
return MouseButtons.Middle;
default:
return MouseButtons.None;
}
}
private MouseEventType GetEventType(Int32 wParam)
{
///
switch (wParam)
{
///
case WM_LBUTTONDOWN:
case WM_RBUTTONDOWN:
case WM_MBUTTONDOWN:
return MouseEventType.MouseDown;
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
return MouseEventType.MouseUp;
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDBLCLK:
return MouseEventType.DoubleClick;
case WM_MOUSEWHEEL:
return MouseEventType.MouseWheel;
case WM_MOUSEMOVE:
return MouseEventType.MouseMove;
default:
return MouseEventType.None;
}
}
#endregion
}
}