c# - 如何将关键事件从控件冒泡到窗体?

标签 c# forms events textbox event-bubbling

我知道 Windows 窗体的 KeyPreview 属性,这允许窗体在键事件传递给焦点控件之前接收键事件。

但是,我希望表单在到达焦点控件后接收事件。

作为测试,我在窗体上放置了一个文本框。在 TextBox 中键入时,它应该在按下某些键命令时执行其默认行为。 Ctrl-S、F1 等,我希望它们通过 TextBox 冒泡到要在更高级别处理的 Form。这些命令是 TextBox 默认不执行的命令。

不过,我确实需要事件先通过 TextBox。需要此功能的应用程序比这个简单示例更复杂。例如,当 TextBox 是焦点控件时,它应该使用 Ctrl-C 和 Ctrl-V 执行默认的复制和粘贴。然而,当各种其他控件获得焦点时,这些命令需要在最顶层的表单级别结束,以便在那里进行处理。

编辑: 似乎输入事件从 Form 转到 Focused Control,而不是像我预期的那样相反。如果它从 Focus 转到 Form,我可能不会遇到我遇到的问题。

编辑2: 已经(简要地)阅读了这篇文章:http://www.codeproject.com/KB/WPF/BeginWPF3.aspx我现在假设我期望只是“在那里”的那种“冒泡”只在 WPF 中可用,而不是标准 C#。我认为我将不得不重新考虑用户与我的应用交互的方式,而不是编写大量丑陋的代码。

对于可以在 C# 中进行 WPF 风格的冒泡而无需丑陋代码的任何人来说,这是重要的一点。

最佳答案

您仍然可以使用 KeyPreview 属性,但检查哪个控件获得焦点,如果它是文本框则什么都不做,否则如果它是另一个控件 - 比如 RichTextBox - 然后处理按下的键。 要获得当前获得焦点的控件,您可能需要访问 Win32 API。 示例:新建一个Windows窗体应用程序,在窗体中添加文本框和富文本框,将窗体的KeyPreview属性设置为true,为窗体、文本框和富文本框添加KeyDown事件的事件处理程序。还有以下 using 语句:

using System.Runtime.InteropServices;//for DllImport

然后用下面的代码替换表单的代码:

public partial class Form1 : Form
{
    // Import GetFocus() from user32.dll
    [DllImport("user32.dll", CharSet = CharSet.Auto, CallingConvention = CallingConvention.Winapi)]
    internal static extern IntPtr GetFocus();

    protected Control GetFocusControl()
    {
        Control focusControl = null;
        IntPtr focusHandle = GetFocus();
        if (focusHandle != IntPtr.Zero)
            // returns null if handle is not to a .NET control
            focusControl = Control.FromHandle(focusHandle);
        return focusControl;
    } 

    public Form1()
    {
        InitializeComponent();
    }

    private void Form1_KeyDown(object sender, KeyEventArgs e)
    {
        Control focusedControl = GetFocusControl();
        if (focusedControl != null && !(focusedControl is TextBox) && e.Control && e.KeyCode == Keys.C)//not a textbox and Copy
        {
            MessageBox.Show("@Form");
            e.Handled = true;
        }
    }

    private void richTextBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if(e.Control && e.KeyCode == Keys.C)
            MessageBox.Show("@Control");
    }

    private void textBox1_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Control && e.KeyCode == Keys.C)
            MessageBox.Show("@Control");
    }
}

关于c# - 如何将关键事件从控件冒泡到窗体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2281828/

相关文章:

javascript - Jquery 获取和设置值

javascript - 为什么焦点处理程序使用错误的参数执行?

events - 全日历单槽事件结束时间

python - Django 模型表单 : Seeding a FK related field in the form

java - 网络线程和 Swing 线程出现问题

javascript - 在 javascript 中创建多项选择选项

Javascript - 使用代码单击图像

c# - 使用 "new() and ".StartNew()"创建新实例有什么区别?

c# - 对象分配

c# - 如何连接 ReadOnlyCollection