读书人

缴获鼠标被按下的消息

发布时间: 2011-12-13 21:22:18 作者: rapoo

截获鼠标被按下的消息
我想截获在任何情况下,鼠标被按下的消息,例如:鼠标在非当前活动窗体外按下时,也要截获鼠标消息,就.NET而言,好像无法解决此问题,只能求助于API,我把我的代码贴出来给大家看一看,我的代码现在就是截获不到鼠标消息,而类似的代码在VB6下是没有问题的,不知道为什么?
答对者,马上结帐.
以下代码是整个窗体的代码,按照我原先的设想,如果捕捉到鼠标消息,就会弹出对话框或输出当前鼠标位置.但就是调试不成功,

public partial class Form2 : Form
{
internal enum HookType //枚举,钩子的类型
{
MsgFilter = -1,
JournalRecord = 0,
JournalPlayback = 1,
Keyboard = 2,
GetMessage = 3,
CallWndProc = 4,
CBT = 5,
SysMsgFilter = 6,
Mouse = 7,
Hardware = 8,
Debug = 9,
Shell = 10,
ForegroundIdle = 11,
CallWndProcRet = 12,
KeyboardLL = 13,
MouseLL = 14,
};

const int WM_LBUTTONDOWN = 0x201;
const int HWND_TOPMOST = -1;
const int HWND_NOTOPMOST = -2;
const int SWP_NOSIZE = 0x1;
const int SWP_NOMOVE = 0x2;
const int SWP_NOACTIVATE = 0x10;
const int SWP_SHOWWINDOW = 0x40;

IntPtr _nextHookPtr; //记录Hook编号

[DllImport( "kernel32.dll ")]
static extern int GetCurrentThreadId(); //取得当前线程编号的API


[DllImport( "User32.dll ")]
internal extern static void UnhookWindowsHookEx(IntPtr handle); //取消Hook的API
[DllImport( "User32.dll ")]
internal extern static IntPtr SetWindowsHookEx(int idHook, [MarshalAs(UnmanagedType.FunctionPtr)] HookProc lpfn, IntPtr hinstance, int threadID); //设置Hook的API
[DllImport( "User32.dll ")]
internal extern static IntPtr CallNextHookEx(IntPtr handle, int code, IntPtr wparam, IntPtr lparam); //取得下一个Hook的API
[DllImport( "User32.dll ")]
internal extern static bool GetCursorPos(ref POINTAPI lpPoint);
[DllImport( "User32.dll ")]
private extern static long SetWindowPos(IntPtr hwnd, long hWndInsertAfter, long X, long y, long cx, long cy, long wFlagslong);
public class POINTAPI
{
public Int32 x;
public Int32 y;
}

internal delegate IntPtr HookProc(int code, IntPtr wparam, IntPtr lparam);

IntPtr MyHookProc(int code, IntPtr wparam, IntPtr lparam)
{
if (code < 0) return CallNextHookEx(_nextHookPtr, code, wparam, lparam); //返回,让后面的程序处理该消息
if (wparam.ToInt32() == WM_LBUTTONDOWN)
{
//POINTAPI pPt = new POINTAPI();
//GetCursorPos(ref pPt);
MessageBox.Show( "hello ");
//this.Text = "mouse click at " + pPt.x.ToString() + ", " + pPt.y.ToString();


return (IntPtr)1; //直接返回了,该消息就处理结束了
}
else
{
return IntPtr.Zero;
}
}

public void SetHook()
{

if (_nextHookPtr != IntPtr.Zero) //已经勾过了
return;
HookProc myhookProc = new HookProc(MyHookProc); //声明一个自己的Hook实现函数的委托对象
_nextHookPtr = SetWindowsHookEx((int)HookType.MouseLL, myhookProc, IntPtr.Zero, GetCurrentThreadId()); //加到Hook链中
}

public void UnHook()
{

if (_nextHookPtr != IntPtr.Zero)
{
UnhookWindowsHookEx(_nextHookPtr); //从Hook链中取消
_nextHookPtr = IntPtr.Zero;
}
}

public Form2()
{
InitializeComponent();
}

private void Form2_Load(object sender, EventArgs e)
{
this.SetHook();
}

private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
this.UnHook();
}



private void Form2_Enter(object sender, EventArgs e)
{
SetWindowPos(this.Handle,-1,0,0,0,0,0);
}
}


[解决办法]
在.NET中,尤其是VS2005的中并不支持全局的Hook,
我不知道说过几次了。。。。


如果非要使用全局的Hook,那么一定要使用非托管的DLL,在非托管的DLL中使用API来实现Hook,然后在C#中像调用API一样调用这个DLL中的方法来实现。

或者使用Application.AddMessageFilter(IMessageFilter value)来添加一个消息过滤器来处理应用程序一级的所有消息。对于一般的不是特别“变态”的问题都能搞定了。
[解决办法]
vb.net下的全局键盘我做过,全局鼠标也应该好用吧,你看看这个符合你要求吗?

http://www.codeproject.com/csharp/globalhook.asp

读书人网 >C#

热点推荐