从WPF应用程序打开的Windows Forms中Alt键和Tab键不起作用

10

我有很多旧的Windows Forms应用程序,最终将被移植到WPF(这是一个大型应用程序,所以无法在一个迭代中完成),我已经通过在WPF中创建主菜单开始了此过程。Windows Forms应用程序是从该菜单打开的独立窗口。

Windows Forms应用程序正常打开和运行,但我遇到了一些问题,其中包括快捷键和Tab键的使用。Tab键无法移动焦点到下一个控件,而Alt键触发“&搜索”按钮的功能也不再起作用。

我做错了什么?

5个回答

8
我发现的一个部分解决方案是在你的WPF构造函数中调用以下内容: System.Windows.Forms.Integration.WindowsFormsHost.EnableWindowsFormsInterop(); (你需要引用WindowsFormsIntegration.dll这个dll文件)
我说部分是因为并不是所有按键都能按预期工作。例如,对于简单的表单,似乎可以正常工作。
请参见此链接:
http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.windowsformshost.enablewindowsformsinterop(v=vs.100).aspx

很有趣,我不知道你可以这样做。谢谢! - Franchesca

4

我通过将winform托管在WPF窗体内的WindowsFormsHost控件中,最终成功解决了这个问题。

public partial class MyWindow : Window
{
    public MyWindow()
    {
        InitializeComponent();

        Form winform = new Form();
        // to embed a winform using windowsFormsHost, you need to explicitly
        // tell the form it is not the top level control or you will get
        // a runtime error.
        winform.TopLevel = false;

        // hide border because it will already have the WPF window border
        winform.FormBorderStyle = System.Windows.Forms.FormBorderStyle.None;
        this.windowsFormsHost.Child = winform;
    }

}

请注意,如果您有一个关闭窗体的按钮,您可能还需要连接winform关闭事件。

3
这是有意设计的。快捷键在消息循环级别处理,检测到窗口获得焦点之前。这就是为什么这些键可以在没有焦点的情况下工作的原因。
问题是,你没有Winforms消息循环来处理消息。在你的程序中,Application.Run()是由WPF实现的,而不是Winforms。因此,任何处理键盘消息以实现快捷键的Winforms代码都不会运行。
这没有好的解决方案,这是一个根本性的“不能有一点怀孕”的问题。由于它允许CAS绕过,Winforms中的这段代码被严格锁定。唯一的解决方法是显示一个包含Winforms控件的Form派生类,并使用其ShowDialog()方法。该方法会启动一个模态消息循环,即Winforms消息循环,足以恢复快捷键处理代码。通过将主窗口转换为对话框,重新构造你的方法。

1
感谢您提供详细的答案。WindowsFormsHost似乎是唯一可以实现快捷键传递的东西。它虽然是为控件设计的,但不适用于“顶级”窗体(因此需要进行一些修改)。 - Franchesca
使用ShowDialog()解决了选项卡问题,对我非常有帮助!我希望其他程序员也能在这里找到这个解决方案(对我来说很难找到)。 - zee

2

我发现另一个处理Tab键焦点的方法是像这样覆盖OnKeyDown:

protected override void OnKeyDown(KeyEventArgs e)
{
    if (e.KeyCode == Keys.Tab)
    {
        HandleFocus(this, ActiveControl);
    }
    else
    {
        base.OnKeyDown(e);
    }
}

internal static void HandleFocus(Control parent, Control current)
{
    Keyboard keyboard = new Keyboard();
    // Move to the first control that can receive focus, taking into account
    // the possibility that the user pressed <Shift>+<Tab>, in which case we
    // need to start at the end and work backwards.
    System.Windows.Forms.Control ctl = parent.GetNextControl(current, !keyboard.ShiftKeyDown);
    while (null != ctl)
    {
        if (ctl.Enabled && ctl.CanSelect)
        {
            ctl.Focus();
            break;
        }
        else
        {
            ctl = parent.GetNextControl(ctl, !keyboard.ShiftKeyDown);
        }
    }
}

这种解决方案的优点在于它不需要WindowsFormsHost或消息泵,这些可能会很麻烦。但我不知道是否可以像这样处理快捷键,因为我没有需要它。

这是一个有趣的方法,对某些人来说可能是一个不错的选择 :) - Franchesca

1

检查是否已分配IsTabStop =“True”TabIndex。 对于Alt + Key快捷方式,尝试使用下划线(_)字符代替&号(&)。


是的,所有相关控件的 isTabStop 属性都设置为 "true"。当我从 winforms 菜单打开窗体时,功能完美运行,但当我从 WPF 菜单打开完全相同的窗体时,它就会出问题了。我不确定你所说的下划线是什么意思。在按钮文本中字母前的&符号当控件呈现时将显示为下划线 :) - Franchesca
@Franchesca 我假设你正在将所有的 WinForms 转换为 WPF。祝你转换顺利! - SliverNinja - MSFT

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接