在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