以下類通過掛載勾子原理,實現將子控件鼠標消息發送給父控件。
調用:
MousePreview mp=new MousePreview(pControl); //pControl爲父控件
//啓用勾子
mp.EnableHook();
//禁用勾子
mp.DisableHook();
using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Windows.Forms;
public class MousePreview
{
/// <summary>
/// Hook管理器
/// </summary>
GCHandle mGC;
[DllImport("kernel32")]
public static extern int GetCurrentThreadId();
/// <summary>
/// 掛載勾子
/// </summary>
/// <param name="idHook"></param>
/// <param name="lpfn"></param>
/// <param name="hmod"></param>
/// <param name="dwThreadId"></param>
/// <returns></returns>
[DllImport("user32", CharSet = CharSet.Auto, CallingConvention = CallingConvention.StdCall)]
public static extern IntPtr SetWindowsHookEx(int idHook, HOOKPROC lpfn, int hmod, int dwThreadId);
/// <summary>
/// 卸載勾子
/// </summary>
/// <param name="hhook"></param>
/// <returns></returns>
[DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
public static extern bool UnhookWindowsHookEx(IntPtr hhook);
/// <summary>
/// 發送消息
/// </summary>
/// <param name="hwnd"></param>
/// <param name="wMsg"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
[DllImport("user32.dll", EntryPoint = "SendMessage")]
public static extern IntPtr SendMessage(IntPtr hwnd, int wMsg, int wParam, int lParam);
public delegate int HOOKPROC(int nCode, int wParam, int lParam);
private Control mControl;
private IntPtr mHook=IntPtr.Zero;
/// <summary>
/// 構造
/// </summary>
/// <param name="pControl"></param>
public MousePreview(Control pControl)
{
mControl = pControl;
}
/// <summary>
/// 啓用掛勾子
/// </summary>
public void EnableHook()
{
if (mHook == IntPtr.Zero)
{
HOOKPROC proc = new HOOKPROC(MyMouseProc);
mGC=GCHandle .Alloc(proc);
mHook = SetWindowsHookEx(7, proc, 0, GetCurrentThreadId());
}
}
/// <summary>
///
/// </summary>
public void DisableHook()
{
if (mHook != IntPtr.Zero)
{
UnhookWindowsHookEx(mHook);
mGC.Free();
}
mHook = IntPtr.Zero;
}
/// <summary>
/// 處理消息事件
/// </summary>
/// <param name="nCode"></param>
/// <param name="wParam"></param>
/// <param name="lParam"></param>
/// <returns></returns>
private int MyMouseProc(int nCode, int wParam, int lParam)
{
if (nCode == 0)
{
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
Rectangle _Rect = mControl.RectangleToScreen(mControl.ClientRectangle);
if (!_Rect.Contains(Cursor.Position)) return 0;
short _X = (short)(Cursor.Position.X - _Rect.X);
short _Y = (short)(Cursor.Position.Y - _Rect.Y);
int _Point = _Y << 16;
_Point += _X;
switch (wParam)
{
case 0x200: //移動鼠標
case 0x201: //按下左鍵
case 0x202: //釋放左鍵
case 0x203: //雙擊左鍵
case 0x204: //按下右鍵
case 0x205: //釋放右鍵
case 0x206: //雙擊右鍵
case 0x207: //按下中鍵
case 0x208: //釋放中鍵
case 0x209: //雙擊中鍵
SendMessage(mControl.Handle, wParam, wParam, _Point);
break;
/*
case 512:
SendMessage(mControl.Handle, 512, wParam, _Point);
break;
case 513:
SendMessage(mControl.Handle, 513, wParam, _Point);
break;
case 514:
SendMessage(mControl.Handle, 514, wParam, _Point);
break;
case 516:
SendMessage(mControl.Handle, 516, wParam, _Point);
break;
case 517:
SendMessage(mControl.Handle, 517, wParam, _Point);
break;
*/
default:
break;
}
}
return 0;
}
}