控制儿童处理程序对同一键盘事件的优先级

时间:2015-03-04 19:22:43

标签: winforms

我有多个具有相同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的简单自定义控件,而c2CefSharp.WinForms.ChromiumWebBrowser。无论我做什么,键盘事件都被c2捕获。

决定处理程序优先级的是什么?我怎样才能改变它?

1 个答案:

答案 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);
    }
}