实现表单级快捷方式,而不拦截子控件的输入

问题描述 投票:3回答:1

我正在使用表单应用程序制作表单级快捷方式。

首先,它适用于条带菜​​单,但它们的快捷方式必须是任何修饰符和单词或小数键的组合。我只需要一个单词或十进制键快捷键。因此它不符合我的需要。

我尝试了一种方法,KeyDownKeyUp事件与形式的KeyPreview设置为true。如果我在这些事件中使用HandledSuppressKeyPress设置为true来处理单词或小数点,则即使控件是TextBoxNumericUpDown(即允许文本输入的控件),子控件也无法接收输入。覆盖ProcessCmdKey也有同样的问题。

然后,我试着通过调用聚焦控制的IsInputKeyIsInputChar来检查聚焦控制实际上是否需要输入。是的,你不能正常调用它们,因为这些方法是protected。我用过反射。但我没有运气。这些没有按照我的预期运作。

最后,我应用了一个检查聚焦控制的分支是TextBox或允许输入的东西。我也没有运气。因为NumericUpDown的真正焦点控制是一个名为UpDownBase.UpDownEdit的私人类。这意味着一些其他控件可以具有在构建时不能期望的类似机制。简而言之,它可能会导致错误。

我想,如果有办法在最后一个关键处理阶段捕获未处理的输入,如冒泡,我可以解决这个问题。但我无法找到有关表单应用程序的信息。

我是否必须覆盖所有子控件'ProcessCmdKeys?

真的没有一种奇特的方法可以解决这个问题吗?

c# winforms
1个回答
0
投票

这是我的快速解决方案。我改变了搜索聚焦控制方法。

在以前,它搜索最深的主动控制。来源来自here。这种方式导致跳过NumericUpDown案例,因为它也是一个容器,并返回其私有控件。

因此,我已将其更改为搜索控件类型,而不是在主动控制链中使用最深的控件类型。

static bool IsFocusedControlType<T>(Control control, out T focused)
    where T : Control
{
    if (control is T t)
    {
        focused = t;
        return true;
    }
    var container = control as IContainerControl;
    while (container != null)
    {
        control = container.ActiveControl;
        if (control is T tt)
        {
            focused = tt;
            return true;
        }
        container = control as IContainerControl;
    }
    focused = null;
    return false;
}

static bool CanConsumeKey(Form sender, KeyEventArgs e)
{
    if (IsFocusedControlType(sender, out NumericUpDown ud))
    {
        return false;
    }
    if (IsFocusedControlType(sender, out TextBox tb) && !tb.ReadOnly)
    {
        return false;
    }
    if (IsFocusedControlType(sender, out ListView lv) && lv.LabelEdit)
    {
        return false;
    }
    if (IsFocusedControlType(sender, out TreeView tv) && tv.LabelEdit)
    {
        return false;
    }
    if (IsFocusedControlType(sender, out ComboBox cb) && 
        cb.DropDownStyle != ComboBoxStyle.DropDownList)
    {
        return false;
    }
    return true;
}

它工作正常,但我认为它不快。

© www.soinside.com 2019 - 2024. All rights reserved.