为了使基于 C++/CLI MFC 的旧应用程序现代化,我们正尝试用用 C#/WPF 编写的新对话框替换旧对话框。为了在内部托管 WPF 控件,CDialog
我们遵循了本指南,其中描述了 Win32 主机窗口的过程:在 Win32 中托管 WPF 内容
这可以工作,但是尽管有 [backspace]/[del]/[space] 等特殊键,WPF 控件内的文本框也不会接受/接收任何键盘输入。
有一个类似的问题:Win32 应用程序中托管的非模态 WPF 对话框不接收键盘事件,其中唯一的答案建议使用HwndSource
在 WPF 控件的程序集中实现消息循环来接收/处理键盘相关消息,但它不起作用。我以这种方式实现了它,但它没有改变任何东西。
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
HwndSource source = (HwndSource)PresentationSource.FromVisual(this);
source.AddHook(WndProc);
}
private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
HwndSource source = HwndSource.FromHwnd(hwnd);
if (source != null)
{
System.Windows.Interop.MSG message = new MSG
{
hwnd = hwnd,
lParam = lParam,
wParam = wParam,
message = msg,
pt_x = 0,
pt_y = 0
};
switch (msg)
{
// WM_KEYDOWN
case 0x0100:
Debug.WriteLine("Received WM_KEYDOWN");
var keyboardSink = (IKeyboardInputSink)source;
keyboardSink.TranslateAccelerator(ref message, Keyboard.Modifiers);
break;
// WM_CHAR
case 0x0102:
Debug.WriteLine("Received WM_CHAR");
var keyboardSink2 = (IKeyboardInputSink)source;
keyboardSink2.TranslateChar(ref message, Keyboard.Modifiers);
break;
}
}
return IntPtr.Zero;
}
但是在裸的 win32 窗口内嵌入相同的 WPF 控件却可以完美运行。
另外,我从主 WPF 控件生成的模态对话框中的文本框也会接收键盘输入,因此它必须与主控件的非模态方式相关。
在这里我提供了一个最小的工作示例来演示该问题:https://github.com/Michaelvsk/WpfHostedInMfc
我对 MFC 的了解非常基础,因此非常感谢任何帮助。
在您的情况下,WPF 控件被托管为
WS_CHILD
Win32 对话框(这很重要)(这也很重要),它会为了自己的利益而吃掉一些消息,就像所有对话框一样。如果你处理WM_GETDLGCODE 消息,你就可以控制它
像这样: