首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > .NET > C# >

缴获鼠标被按下的消息

2011-12-13 
截获鼠标被按下的消息我想截获在任何情况下,鼠标被按下的消息,例如:鼠标在非当前活动窗体外按下时,也要截

截获鼠标被按下的消息
我想截获在任何情况下,鼠标被按下的消息,例如:鼠标在非当前活动窗体外按下时,也要截获鼠标消息,就.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

热点排行