mouseWheel in WindowsFormsHost(鼠标滚轮事件)

在wpf应用程序中有WindowsFormsHost,可以使用wpf UI与winform或者 win32窗口进行交互,但是实际上,对于键盘事件及鼠标部分事件,是无法获取到的,如下所提的

http://social.msdn.microsoft.com/Forums/en/wpf/thread/2f927aa6-834a-41a3-affa-7188377f71cf

 

因此更好的解决方法可能是以下提到:

http://hi.baidu.com/%CB%BC%D1%C4%CC%EC%BF%D5/blog/item/a41f13087aa067dc62d986a2.html

 

在托管环境中使用钩子截获事件主要方法如下:

/// <summary>

        /// 键盘钩子

        /// </summary>

         public event SceneKeyBoardProcHandle pSceneKeyBoardProcHandle;

         public long OnSceneKeyBoardProcHandle(intnCode, IntPtrwParam, IntPtrlParam)

         {

             if (pNativeWndCreate.m_bHasCatchKeyBoard && nCode >= 0)

             {

                 if(lParam.ToInt64()>0)//键盘按下

                    pNativeWndCreate.CallWinProc(Win32MessageIdMapping.WM_KEYDOWN, wParam,lParam);

                 else if(lParam.ToInt64()<0)// 键盘弹起

                    pNativeWndCreate.CallWinProc(Win32MessageIdMapping.WM_KEYUP, wParam,lParam);

                 nCode = -1;

             }

             return pNativeWndCreate.CallNextHookEx(HookType.KeyBoard, nCode,wParam, lParam);

 

         }

因为钩子事件是线程级别,因此,而我们需要可能是只针对我们所指的窗口事件,以下以鼠标滚轮事件为例,来说明这个问题

  /// <summary>

        /// 使用钩子截获窗口滚轮事件时,将会得到当前线程所有窗口下滚轮事件,无法区分是否该3d窗口

        /// 而mouseover可以区分出是哪个窗口中,因为使用m_bMouseOver来标识鼠标是否在该窗口下,

        /// 然后再截获滚轮事件

        /// </summary>

         private bool m_bMouseOver = false;

        /// <summary>

        /// 鼠标钩子,只是为了获取滚轮事件

        /// 在没有安装钩子的时候,如果用了winhost,

        /// 那么wpf Main窗口的鼠标滚轮事件也无法获取

        /// </summary>

         public event SceneMouseProcHandle pMouseProcHandle= null;

         public long OnMouseProcHandle(intnCode, IntPtrwParam, IntPtrlParam)

         {

             tagMOUSEHOOKSTRUCT pMouseHook= new tagMOUSEHOOKSTRUCT();

             pMouseHook = (tagMOUSEHOOKSTRUCT)Marshal.PtrToStructure(lParam, typeof(tagMOUSEHOOKSTRUCT));

             if (pMouseHook.hwnd != IntPtr.Zero

                && pNativeWndCreate.m_bHasCatchMouse

                && nCode >= 0)

             {

                 if (wParam.ToInt64() == Win32MessageIdMapping.WM_MOUSEMOVE)

                 {

                    if (pMouseHook.hwnd.ToInt64()== pHwndHost.ToInt64())

                    {

                        m_bMouseOver = true;

                    }

                    else

                        m_bMouseOver = false;

                 }

                 else if (m_bMouseOver == true&& wParam.ToInt64()== Win32MessageIdMapping.WM_MOUSEWHEEL)

                 {

                    pNativeWndCreate.CallWinProc(Win32MessageIdMapping.WM_MOUSEWHEEL, wParam,lParam);

                 }

                 nCode = -1;

             }

             return pNativeWndCreate.CallNextHookEx(HookType.Mouse, nCode, wParam, lParam);

         }

   /// <summary>

         /// 三维窗口消息处理程序(也可以通过MessageHook获取实现)

        /// </summary>

        public event NativeWndProc pNativeWndProc;

        public long OnNativeWndProc(IntPtrhWnd,uint msg, IntPtr wParam, IntPtr lParam)

        {

          

            switch (msg)

            {

                case Win32MessageIdMapping.WM_DESTROY:

                   Win32PinvokeUtilities.PostQuitMessage(0);

                   return 0;

                case Win32MessageIdMapping.WM_KEYDOWN:

                   {

                       MessageBox.Show("WM_KEYDOWN");

                      break;

                   }

                case Win32MessageIdMapping.WM_KEYUP:

                   {

                       MessageBox.Show("WM_KEYUP");

                       break;

                   }

         

                case Win32MessageIdMapping.WM_SIZE:

                   {

                       int newWidth= Win32PinvokeUtilities.LoWord(lParam.ToInt32());

                       int newHeight= Win32PinvokeUtilities.HiWord(lParam.ToInt32());

                       //if((newWidth>0&&newHeight>0)&& (hostWidth!=newWidth ||hostHeight!=newHeight))

                       //{

                            hostWidth=newWidth;

                            hostHeight = newHeight;

                          //MessageBox.Show("窗口创建不成功");

                         

                       //}

                       break;

                   }

 

                case Win32MessageIdMapping.WM_LBUTTONDOWN:

                case Win32MessageIdMapping.WM_RBUTTONDOWN:

                   {

 

                       MessageBox.Show("窗口创建不成功");

                       break;

                   }

                case Win32MessageIdMapping.WM_LBUTTONUP:

                case Win32MessageIdMapping.WM_RBUTTONUP:

                   {

                      

                       break;

                   }

                case Win32MessageIdMapping.WM_MOUSEWHEEL:

                    {

                       

 

                        tagMOUSEHOOKSTRUCTEX pMouseHookEx= new tagMOUSEHOOKSTRUCTEX();

                        pMouseHookEx = (tagMOUSEHOOKSTRUCTEX)Marshal.PtrToStructure(lParam,typeof(tagMOUSEHOOKSTRUCTEX));

                        MessageBox.Show(((short)(pMouseHookEx.mouseData/65536)).ToString());

                        break;

                    }

                case Win32MessageIdMapping.WM_MOUSEHOVER:

                   {

                       //MessageBox.Show("WM_MOUSEHOVER");

 

                     

                   }

                    break;

                case Win32MessageIdMapping.WM_MOUSELEAVE:

                   {

                       MessageBox.Show("WM_MOUSELEAVE");

                   }

                   break;

                case Win32MessageIdMapping.WM_MOUSEMOVE:

                   {

                                           break;

                   }

                default:

                   break;

            }

            return Win32PinvokeUtilities.DefWindowProc(hWnd,msg, wParam,lParam);

        }

 

 

以上涉及的结构体和托管类型的 p/invoke 声明

 

namespace MyWndTest

{

    //  [8/8/2011 zwq]

    /// <summary>

    /// 构建int与win32键盘的对应关系,参照WinUser.h

    /// </summary>

    public struct KeyBoardMapping

    {

        internal const int

          VK_LEFT = 0x25,

          VK_UP = 0x26,

          VK_RIGHT = 0x27,

          VK_DOWN = 0x28,

 

          VK_W = 0x57,

          VK_S = 0x53,

          VK_A = 0x41,

          VK_D = 0x44,

          VK_R = 0x52;

    }

    //  [8/9/2011 zwq]

    /// <summary>

    /// 构建int与win32消息的对应关系,参照WinUser.h

    /// </summary>

    public struct Win32MessageIdMapping

    {

        internal const int

         WM_KEYDOWN = 0x0100,

         WM_KEYUP = 0x0101,

         WM_SIZE = 0x0005,

         WM_COMMAND = 0x00000111,

         WM_DESTROY = 0x0002,

         WM_MBUTTONDOWN =0x0207,

         WM_MBUTTONUP = 0x0208,

         WM_MOUSEMOVE = 0x0200,

         WM_LBUTTONDOWN = 0x0201,

         WM_LBUTTONUP= 0x0202,

         WM_RBUTTONDOWN = 0x0204,

         WM_RBUTTONUP = 0x0205,

         WM_MOUSEWHEEL = 0x020A,

         WM_MOUSEHOVER =0x02A1,

         WM_MOUSELEAVE = 0x02A3,

         WM_LBUTTONDBLCLK =0x0203;

    }

 

    //  [8/9/2011 zwq]

    /// <summary>

    /// 构建int与win32样式的对应关系,参照WinUser.h

    /// </summary>

    public struct Win32StyleMapping

    {

        internal const int

          CS_VREDRAW = 0x0001,

          CS_HREDRAW = 0x0002,

          WS_CHILD = 0x40000000,

          WS_VISIBLE = 0x10000000,

          WS_CLIPSIBLINGS = 0x04000000,

          WS_CLIPCHILDREN = 0x02000000,

          WS_VSCROLL = 0x00200000,

          WS_BORDER = 0x00800000;

    }

 

    public class Win32PinvokeUtilities

    {

        [DllImport("Kernel32.dll")]

        [return: MarshalAs(UnmanagedType.U4)]

        internal static extern uint GetTickCount();

 

        [DllImport("user32.dll",EntryPoint = "DestroyWindow",CharSet = CharSet.Unicode)]

        internal static extern bool DestroyWindow(IntPtrhwnd);

 

        [DllImport("user32.dll",EntryPoint = "PostQuitMessage")]

        internal static extern void PostQuitMessage(intnExitCode);

 

        [DllImport("user32.dll",EntryPoint = "DefWindowProc")]

        internal static extern long DefWindowProc(IntPtrhWnd,uint msg,IntPtr wParam,IntPtr lParam);

 

 

        public static int HiWord(int number)

        {

            if ((number &0x80000000) == 0x80000000)

                return (number>> 16);

            else

                return (number>> 16) & 0xffff;

        }

 

        public static int LoWord(int number)

        {

            return number& 0xffff;

        }

    }

 

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]

    public struct tagMOUSEHOOKSTRUCT

    {

        /// POINT->tagPOINT

        public Point pt;

 

        /// HWND->HWND__*

        public System.IntPtr hwnd;

 

        /// UINT->unsigned int

        public uint wHitTestCode;

 

        /// ULONG_PTR->unsignedint

        public uint dwExtraInfo;

    }

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]

    public struct tagMOUSEHOOKSTRUCTEX

    {

        tagMOUSEHOOKSTRUCT mouseBaseinfo;

        /// DWORD -> unsignedint

        public uint mouseData;

    }

 

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]

    public struct Point

    {

 

        /// LONG->int

        public int x;

 

        /// LONG->int

        public int y;

    }

 

    [System.Runtime.InteropServices.StructLayoutAttribute(System.Runtime.InteropServices.LayoutKind.Sequential)]

    public struct HWND__

    {

 

        /// int

        public int unused;

    }

}

参考:

http://www.99inf.net/SoftwareDev/VC/13171.htm

http://www.microsoft.com/china/community/program/originalarticles/techdoc/hook.mspx

http://www.cnblogs.com/forlina/archive/2011/7/28.html

http://blog.csdn.net/leehyfer/article/details/5040879

http://tech.ddvip.com/2009-05/1242809061120145.html

 


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值