如何将控件中的关键事件冒泡到表单?

时间:2010-02-17 15:19:23

标签: c# forms events textbox event-bubbling

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

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

作为测试,我在表单上放置了一个TextBox。键入TextBox后,按下某些键命令后,它应该执行默认行为。 Ctrl-S,F1等,我希望那些通过TextBox冒泡到Form以便在更高级别处理。这些命令是TextBox默认不执行的命令。

我确实需要事件首先通过TextBox。需要此功能的应用程序比这个简单示例更复杂。例如,当TextBox是聚焦控件时,它应该执行默认的Copy&使用Ctrl-C和Ctrl-V粘贴。但是,当关注各种其他控件时,这些命令最终需要在最顶层的Form级别进行处理。

修改 看起来输入事件从Form到Focused Control,而不是像我期望的那样。如果它从Focus变为Form我可能不会遇到问题。

EDIT2: 通过本文阅读(简要):http://www.codeproject.com/KB/WPF/BeginWPF3.aspx我现在假设我希望“在那里”的'冒泡'只能在WPF中使用,而不是标准的C#。我想我将不得不重新考虑用户与我的应用程序交互的方式,而不是编写丑陋的代码。

对于那些能够回答在C#中进行WPF风格冒泡而没有丑陋代码的人来说,这一点非常重要。

4 个答案:

答案 0 :(得分:2)

您仍然可以使用KeyPreview属性,但检查哪个控件是焦点,如果它是文本框则不执行任何操作,否则如果它是另一个控件 - 比如RichTextBox - 则处理按下的键。 要获得当前的焦点控件,您可能需要访问Win32 API。 示例:创建一个新的Windows窗体应用程序,在窗体中添加一个文本框和一个richtext框,将窗体的KeyPreview属性设置为true,为窗体,文本框和richtextbox的KeyDown事件添加事件处理程序。还有以下使用声明:

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");
    }
}

答案 1 :(得分:0)

查看下面给出的链接。

http://www.vbdotnetforums.com/windows-forms/30257-solved-ctrl-s-combobox.html

希望这有帮助。

此致 拉加

答案 2 :(得分:0)

你不得不手动实现它 - 在表单中实现KeyDown事件处理程序,检查全局组合键并为它们设置KeyPressEventArgs.Handled = true。

供参考:http://msdn.microsoft.com/en-us/library/system.windows.forms.control.keydown.aspx

答案 3 :(得分:-1)

您可以为文本框的KeyPress和/或KeyUp / KeyDown事件实现事件处理程序。

在KeyPress事件的事件处理程序中,如果将事件args上的Handled属性设置为true,则事件将不会传递到文本框。如果你没有将它设置为true,那就是。

(编辑澄清第二段)。