【问题标题】:Alt keys and tab don't work in Windows Forms opened from a WPF applicationAlt 键和选项卡在从 WPF 应用程序打开的 Windows 窗体中不起作用
【发布时间】:2012-02-23 10:11:25
【问题描述】:

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

Windows 窗体应用程序正在打开并正常工作,除了我在使用快捷键和 Tab 键时遇到的问题。 tab 键没有将焦点移动到下一个控件,并且触发 &Search 按钮的 Alt 键不再起作用。

我做错了什么?

【问题讨论】:

    标签: c# wpf winforms alt-key


    【解决方案1】:

    我发现处理 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 也不需要可能难以实施的消息泵。但是我不知道是否可以处理这样的快捷键,因为我不需要它。

    【讨论】:

    • 这是一种有趣的方法,对某人来说可能是一个不错的选择:)
    【解决方案2】:

    我发现的一个部分解决方案是从您的 WPF 构造函数中调用它: System.Windows.Forms.Integration.WindowsFormsHost.EnableWindowsFormsInterop(); (需要引用dll WindowsFormsIntegration.dll)

    我说部分是因为并非所有击键都按预期工作。例如,对于简单的表单似乎可以正常工作。

    看这个:
    http://msdn.microsoft.com/en-us/library/system.windows.forms.integration.windowsformshost.enablewindowsformsinterop(v=vs.100).aspx

    【讨论】:

    • 这很有趣,我不知道你可以那样做。谢谢!
    【解决方案3】:

    这是设计使然。快捷键在消息循环级别处理,在 Windows 消息发送到具有焦点的窗口之前检测到。这就是无论焦点如何,这些键都可以工作的原因。

    问题是,您没有 Winforms 消息循环泵送消息。 Application.Run() 由 WPF 在您的程序中实现,而不是 Winforms。因此,Winforms 中处理键盘消息以实现快捷键的任何代码都不会运行。

    对此没有好的解决方案,基本上是“无法怀孕”的问题。 Winforms 中的这段代码被严重锁定,因为它允许绕过 CAS。唯一的解决方法是使用其 ShowDialog() 方法显示包含 Winforms 控件的 Form 派生类。该方法泵出一个模态消息循环,即 Winforms 循环,足以恢复快捷键处理代码。通过首先转换主窗口,最后转换对话框来重组您的方法。

    【讨论】:

    • 感谢您的详细解答。 WindowsFormsHost 似乎是唯一有助于传递快捷键的东西。但它是为控件设计的,而不是“顶级”表单(因此需要一些黑客攻击)。
    • ShowDialog() 的使用解决了标签问题,对我很有帮助!我希望其他程序员能在这里找到这个解决方案(我很难找到)
    【解决方案4】:

    我终于设法通过在 WPF 表单内的 WindowsFormsHost 控件中托管 winform 来解决此问题。

    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 关闭事件。

    【讨论】:

      【解决方案5】:

      检查是否分配了IsTabStop="True"TabIndex。对于Alt + Key 快捷方式,请尝试使用下划线 (_) 字符而不是与符号 (&)。

      【讨论】:

      • 是的,isTabStop="true" 适用于所有相关控件。当我从 winforms 菜单打开表单时,该功能完美运行,只有当我从 WPF 菜单打开完全相同的表单时,它才会中断。我不确定您使用下划线是什么意思。在呈现控件时,按钮文本中字母前的 & 符号当然会显示为下划线:)
      • @Franchesca 我假设您正在将所有 winform 转换为 WPF。祝您转化成功!
      猜你喜欢
      • 2010-10-18
      • 2013-07-02
      • 2014-08-16
      • 1970-01-01
      • 2013-11-14
      • 2014-07-03
      • 1970-01-01
      • 2012-07-22
      • 1970-01-01
      相关资源
      最近更新 更多