我正在使用表单应用程序制作表单级快捷方式。
首先,它适用于条带菜单,但它们的快捷方式必须是任何修饰符和单词或小数键的组合。我只需要一个单词或十进制键快捷键。因此它不符合我的需要。
我尝试了一种方法,KeyDown
和KeyUp
事件与形式的KeyPreview
设置为true
。如果我在这些事件中使用Handled
和SuppressKeyPress
设置为true
来处理单词或小数点,则即使控件是TextBox
或NumericUpDown
(即允许文本输入的控件),子控件也无法接收输入。覆盖ProcessCmdKey
也有同样的问题。
然后,我试着通过调用聚焦控制的IsInputKey
和IsInputChar
来检查聚焦控制实际上是否需要输入。是的,你不能正常调用它们,因为这些方法是protected
。我用过反射。但我没有运气。这些没有按照我的预期运作。
最后,我应用了一个检查聚焦控制的分支是TextBox
或允许输入的东西。我也没有运气。因为NumericUpDown
的真正焦点控制是一个名为UpDownBase.UpDownEdit
的私人类。这意味着一些其他控件可以具有在构建时不能期望的类似机制。简而言之,它可能会导致错误。
我想,如果有办法在最后一个关键处理阶段捕获未处理的输入,如冒泡,我可以解决这个问题。但我无法找到有关表单应用程序的信息。
我是否必须覆盖所有子控件'ProcessCmdKey
s?
真的没有一种奇特的方法可以解决这个问题吗?
这是我的快速解决方案。我改变了搜索聚焦控制方法。
在以前,它搜索最深的主动控制。来源来自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;
}
它工作正常,但我认为它不快。