我们可以在不创建自定义控件的情况下拦截多个 TextBox 的 KeyPress 事件吗? [英] Can we intercept KeyPress events of multiple TextBoxes without creating a Custom Control?

查看:17
本文介绍了我们可以在不创建自定义控件的情况下拦截多个 TextBox 的 KeyPress 事件吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有什么方法可以在不添加用户控件的情况下覆盖 TextBox 的原始 KeyPress 事件的行为?

Is there any way we can override the behavior of the original KeyPress event of a TextBox without adding a UserControl?

我的问题是:
我有一个大项目,其中有 1000 多个文本框.那些驻留在不同的形式.我必须验证用户输入以防止输入特殊字符.

My problem is this:
I have a big project where I have over 1000 TextBoxes. Those reside in different Forms. I have to validate user input to prevent entering special characters.

我知道防止这种情况发生的代码,但是我必须将该代码放在每个 TextBox 的每个 KeyPress 事件处理程序中,或者我必须制作一个从 TextBox 类派生的自定义控件,覆盖 OnKeypress,如果在 Forms 上的 KeyPress 事件中明确声明了代码,则调用基类并替换无处不在的自定义控件.

I know the code to prevent that, but then I have to put that code in every KeyPress event handler of each TextBox, or I have to make a Custom Control derived from TextBox class, override OnKeypress, call the base class in case if there are explicitly codes declared in KeyPress events on Forms and replace the Custom Control everywhere.

是否有其他方法可以拦截 TextBox 的 KeyPress 事件并仅在一个地方进行此更改?

Is there any other method to intercept the KeyPress events of a TextBox and make this change in one place only?

推荐答案

举几个例子:

  1. 一个简单的共享类,允许使用预定义的事件处理程序订阅事件.
  2. 一个自定义控件,可以根据特定的允许模式过滤按键操作.在这里,我使用的是您之前发布的与 KeyPress 事件过滤器相关的内容.这个过滤器可能需要多加注意.
    作为示例,我添加了一个公共属性 public bool NumbersOnly,它可用于使自定义 TextBox 控件只接受数字.当它被激活时,它会从任何非数字字符中清除文本.当按下不允许的键时,ErrorProvider 会给出反馈.
  1. A simple shared class that allows to subscribe to events using predefined event handlers.
  2. A Custom Control that can filter key presses based on specific allowed patterns. Here, I'm using what you posted earlier in relation to the KeyPress event filters. This filter may need some more attention.
    I've added, as an example, a public Property, public bool NumbersOnly, which can be used to make the custom TextBox control accept only numbers. It purges the text from any non digits chars when it's activated. An ErrorProvider gives feedback when a key that is not allowed is pressed.

示例集中式事件处理程序.

public partial class SomeForm : Form
{
    public SomeForm()
    {
        InitializeComponent();

        // Get all TextBoxes in the current Form and subscribe to some events 
        foreach (var textBox in this.FindAll<TextBox>()) {
            textBox.TextChanged += MyEventsHandler.TextBoxTextChanged_Handler;
            textBox.KeyPress += MyEventsHandler.TextBoxKeyPress_Handler;
    }

    protected override void OnFormClosing(FormClosingEventArgs e)
    {
        foreach (var textBox in this.FindAll<TextBox>()) {
            textBox.TextChanged -= MyEventsHandler.TextBoxTextChanged_Handler;
            textBox.KeyPress -= MyEventsHandler.TextBoxKeyPress_Handler;
        }
        base.OnFormClosing(e);
    }
}

简单事件处理程序类:

internal static class MyEventsHandler
{
    internal static void TextBoxTextChanged_Handler(object sender, EventArgs e)
    {
        var txt = sender as TextBox;
        Console.WriteLine(txt.Text);
    }

    internal static void TextBoxKeyPress_Handler(object sender, KeyPressEventArgs e)
    {
        if (Regex.Match(e.KeyChar.ToString(), @"[^a-zA-Z0-9\s]").Success) {
            e.Handled = true;
        }
    }
}

扩展方法:

public static class ControlExtensions
{
    public static IEnumerable<T> FindAll<T>(this Control control) where T: Control
    {
        foreach (Control ctl in control.Controls) {
            foreach (Control child in ctl.FindAll<T>()) {
                if (child is T ch) yield return ch;
            }
            if (ctl is T c) yield return c;
        }
    }
}

专用自定义控件,继承TextBox

IMO,最好将所有过滤逻辑都集中在一个控件中,以便在需要时可以进一步扩展

IMO, it's better to have all the filtering logic in one single Control that can be further expanded when needed

using System;
using System.ComponentModel;
using System.Security.Permissions;
using System.Text.RegularExpressions;
using System.Windows.Forms;

[ToolboxItem(true)]
[DesignerCategory("Code")]
public class TextBoxEx : TextBox
{
    private const int ES_NUMBER = 0x2000;
    private bool m_NumbersOnly = false;
    private Regex regex = new Regex(@"[^a-zA-Z0-9\s\b]", RegexOptions.Compiled);

    public TextBoxEx() { }

    public bool NumbersOnly {
        get => m_NumbersOnly;
        set {
            if (m_NumbersOnly != value) {
                m_NumbersOnly = value;
                this.Text = Regex.Replace(this.Text, @"\D", "");
                this.RecreateHandle();
            }
        }
    }

    protected override void OnKeyPress(KeyPressEventArgs e)
    {
        if (regex.IsMatch(e.KeyChar.ToString())) {
            e.Handled = true;
        }
        base.OnKeyPress(e);
    }

    protected override CreateParams CreateParams
    {
        [SecurityPermission(SecurityAction.LinkDemand, Flags = SecurityPermissionFlag.UnmanagedCode)]
        get {
            CreateParams cp = base.CreateParams;
            if (m_NumbersOnly) {
                cp.Style |= ES_NUMBER;
            }
            else {
                cp.Style &= ~ES_NUMBER;
            }
            return cp;
        }
    }
}

这篇关于我们可以在不创建自定义控件的情况下拦截多个 TextBox 的 KeyPress 事件吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆