WPF与Win32控件互操作:键盘按键后焦点被转移问题

  问题描述:

    已有一个通过改写的MFC Grid控件,通过 WindowsFormsHost  承载在WPF界面中。选定某一单元格,按下键盘方向键(如 Right),此时焦点从MFC控件中跳出并被转移至WPF界面(此时MFC 控件无法接获到 KeyDown 消息, 正常情况下,MFC控件通过此消息事件选中按键所指单元格)。

  通过类型定义可以看到,WindowsFormsHost 通过 HwndHost 进行实现,该类是一个用于WPF中嵌入其他技术框架所开发界面,并与之进行交互的抽象类,它继承了 IWin32Window、 IKeyboardInputSink,分别用于窗口句柄 及 键盘消息处理。

  资料介绍:

    1、 HwndHost 官方文档的注解部分可以找到WPF 和 Win32 互操作,这里给出了较为详细的WPF互操作相关信息,及对应的示例程序。

    2、除官方文档外,还有 Adam Nathan的博客 亦有介绍。

  解决方法:

    基于 HwndHost 实现一个托管宿主类,重写 TranslateAcceleratorCore 方法,不再使用基类中的虚方法实现,并将在重写方法中使用 API 转发消息到 MFC 窗体。具体代码如下:

复制代码
 1     public class Win32Host : HwndHost
 2     {
 3         public static readonly DependencyProperty HandleProperty = DependencyProperty.Register("Handle", typeof(IntPtr), typeof(Win32Host), new PropertyMetadata(IntPtr.Zero));
 4 
 5         new public IntPtr Handle
 6         {
 7             get { return (IntPtr)GetValue(HandleProperty); }
 8             set { SetValue(HandleProperty, value); }
 9         }
10         protected override HandleRef BuildWindowCore(HandleRef hwndParent)
11         {
12             Handle = CreateWindowEx(
13                 0, "static", "",
14                 WS_CHILD | WS_VISIBLE | LBS_NOTIFY,
15                 0, 0,
16                 (int)Width, (int)Height,
17                 hwndParent.Handle,
18                 IntPtr.Zero,
19                 IntPtr.Zero,
20                 0);
21             return new HandleRef(this, Handle);
22         }
23         protected override void DestroyWindowCore(HandleRef hwnd)
24         {
25             DestroyWindow(hwnd.Handle);
26         }
27 
28         protected override bool TranslateAcceleratorCore(ref MSG msg, ModifierKeys modifiers)
29         {
30             SendMessage(msg.hwnd, msg.message, msg.wParam, msg.lParam);
31             return true;
32         }
33 
34 
35         const int WS_CHILD = 0x40000000;
36         const int WS_VISIBLE = 0x10000000;
37         const int LBS_NOTIFY = 0x001;
38         [DllImport("user32.dll")]
39         internal static extern IntPtr CreateWindowEx(int exStyle, string className, string windowName, int style, int x, int y, int width, int height, IntPtr hwndParent, IntPtr hMenu, IntPtr hInstance, [MarshalAs(UnmanagedType.AsAny)] object pvParam);
40         [DllImport("user32.dll")]
41         static extern bool DestroyWindow(IntPtr hwnd);
42         [DllImport("user32.dll")]
43         public static extern IntPtr SetFocus(IntPtr hWnd);
44         [DllImport("user32.dll")]
45         public static extern IntPtr SendMessage(IntPtr hWnd, int msg, IntPtr wParam, IntPtr lParam);
46     }
Win32Host
复制代码

  

  

posted @   KnightWelling  阅读(195)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能
点击右上角即可分享
微信分享提示