我有多个具有相同WinForms格式的子节点,每个子节点都有自己的键盘事件处理程序。对于一个最小的例子(C#):
public Form1() {
InitializeComponent();
c1 = new Control();
c2 = new Control();
c1.KeyPress += c1_KeyPress;
c2.KeyPress += c2_KeyPress;
Controls.Add(c1);
Controls.Add(c2);
}
void c1_KeyPress(object sender, KeyPressEventArgs e) {
Text += " c1";
e.Handled = true;
}
void c2_KeyPress(object sender, KeyPressEventArgs e) {
Text += " c2";
e.Handled = true;
}
当事件触发时,它总是由最初添加到表单中的任何一个孩子处理。使用c2.BringToFront()
或Controls.SetChildIndex(c2, 0)
对子女进行重新排序并不会更改优先级。重新排序构造或委托分配也不会改变任何东西。拨打c2.Focus()
也不会。更改Add
调用的顺序是唯一似乎影响它的方法。
(相比之下,对于鼠标事件,优先级以预期的方式得到解决:指针热点下的最顶层控件获取事件的dib,而#34; topmost"是清晰的概念我可以使用BringToFront
和朋友来控制。)
在我的实际案例中,c1
是一个源自WinForms.UserControl
的简单自定义控件,而c2
是CefSharp.WinForms.ChromiumWebBrowser
。无论我做什么,键盘事件都被c2
捕获。
决定处理程序优先级的是什么?我怎样才能改变它?
答案 0 :(得分:1)
没有"优先级",在具有焦点的控件上引发键盘事件。直观易懂,在TextBox中输入文本需要先选择它。已发布代码段中的一个非常重要的缺陷是,您无法分辨哪一个具有焦点。虽然Control类可以按原样使用,但实际上你几乎总是需要从它派生自己的类来给它提供理想的行为。
在项目中添加一个新类并粘贴下面显示的代码。将new Control()
替换为new MyControl()
。现在你可以告诉。
using System;
using System.Windows.Forms;
class MyControl : Control {
protected override void OnEnter(EventArgs e) {
this.Invalidate();
base.OnEnter(e);
}
protected override void OnLeave(EventArgs e) {
this.Invalidate();
base.OnLeave(e);
}
protected override void OnPaint(PaintEventArgs e) {
if (this.Focused) {
ControlPaint.DrawFocusRectangle(e.Graphics, this.DisplayRectangle);
}
base.OnPaint(e);
}
}