在C#中处理粘贴事件

7

我创建了一个静态类 numeric Textbox,但我想控制用户在文本框中粘贴的内容。为了处理粘贴事件,我使用 textchanged 事件:

        static public void textChanged(EventArgs e, TextBox textbox, double tailleMini, double tailleMaxi, string carNonAutorisé)
    {            
        //Recherche dans la TextBox, la première occurrence de l'expression régulière.
        Match match = Regex.Match(textbox.Text, carNonAutorisé);
        /*Si il y a une Mauvaise occurence:
         *   - On efface le contenu collé
         *   - On prévient l'utilisateur 
         */
        if (match.Success)
        {
            textbox.Text = "";
            MessageBox.Show("Votre copie un ou des caractère(s) non autorisé", "Attention", MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
        tailleTextBox(textbox, tailleMini, tailleMaxi);
    }

在另一个类中,我会像这样使用这个静态方法。
    private void tbxSigné_TextChanged(object sender, EventArgs e)
    {
        FiltreTbx.textChanged(e, tbxSigné, double.MinValue, double.MaxValue, @"[^\d\,\;\.\-]");
    }

我希望您能够做类似于以下的事情:
  if (match.Success)
    {
        textbox.Text = //Write the text before users paste in the textbox;

    }

请问有人有想法吗?


C# 2.0 是一个实际的限制吗?使用 C# 3.0 的解决方案会更加优雅。 - Thorarin
是的,我被迫使用C# 2.0... - user2276091
我忘记了变量捕获实际上是在C# 2中引入的,尽管Lambda是版本3。我已经添加了一些你可能能够使用的选项。 - Thorarin
1个回答

11

首先,您是否考虑使用MaskedTextBox? 它可以为您处理字符过滤。

然而,出于练习的目的,您可以考虑沿着以下思路解决。以下是用法:

public Form1()
{
    InitializeComponent();

    FiltreTbx.AddTextBoxFilter(tbxSigné,
                               double.MinValue, double.MaxValue,
                               @"[^\d\,\;\.\-]");
}

这个 AddTextBoxFilter 是一个新的静态方法,你只需要调用一次。它会为 TextBox 添加一个 TextChanged 处理程序。该处理程序使用 闭包 来存储文本框中先前的 Text

你的静态方法获得了一个额外的参数,以传递先前的文本。

public class FiltreTbx
{
    public static void AddTextBoxFilter(TextBox textbox,
                                        double tailleMini, double tailleMaxi,
                                        string carNonAutorisé)
    {
        string previousText = textbox.Text;

        textbox.TextChanged +=
            delegate(object sender, EventArgs e)
            {
                 textChanged(e, textbox, tailleMini, tailleMaxi,
                             carNonAutorisé, previousText);
                 previousText = textbox.Text;
            };
    }

    static public void textChanged(EventArgs e, TextBox textbox,
                                   double tailleMini, double tailleMaxi,
                                   string carNonAutorisé, string previousText)
    {
        //Recherche dans la TextBox, la première occurrence de l'expression régulière.
        Match match = Regex.Match(textbox.Text, carNonAutorisé);
        /*Si il y a une Mauvaise occurence:
         *   - On efface le contenu collé
         *   - On prévient l'utilisateur 
         */
        if (match.Success)
        {
            // Set the Text back to the value it had after the previous
            // TextChanged event.
            textbox.Text = previousText;
            MessageBox.Show("Votre copie un ou des caractère(s) non autorisé",
                            "Attention", MessageBoxButtons.OK,
                            MessageBoxIcon.Information);
        }
        tailleTextBox(textbox, tailleMini, tailleMaxi);
    }
}

我不确定tailleTextBox的确切作用,因为您没有包含该源代码,但我猜它强制执行最小和最大值?

替代方案

如果你想在粘贴操作发生之前自己处理它,你需要拦截文本框的WM_PASTE消息。一种方法是创建一个专门的控件:

using System;
using System.Windows.Forms;

class MyTextBox : TextBox
{
    private const int WM_PASTE = 0x0302;

    protected override void WndProc(ref Message m)
    {
        if (m.Msg != WM_PASTE)
        {
            // Handle all other messages normally
            base.WndProc(ref m);
        }
        else
        {
            // Some simplified example code that complete replaces the
            // text box content only if the clipboard contains a valid double.
            // I'll leave improvement of this behavior as an exercise :)
            double value;
            if (double.TryParse(Clipboard.GetText(), out value))
            {
                Text = value.ToString();
            }
        }
    }
}
如果你在你的WinForms项目中定义了这个类,你就可以像拖动任何其他控件一样把它拖到你的表单上。

谢谢!!我将使用您的第一种解决方案!我不能使用掩码文本框,因为我正在处理许多文本框的项目。关于tailleTextBox方法,您是正确的,这是一个选择最大值和最小值的方法。 - user2276091
你有没有想过,如果粘贴正确,就把之前的文本删除的办法? - user2276091
你不能删除它,因为在粘贴发生之前必须已经初始化。每个文本框只是多了一个额外的字符串,我不会担心它。如果你有很多文本框,创建一个专门的控件可能更实用,但这取决于你 :) - Thorarin
是的,你说得对!我最终选择了你提供的专用控件和静态方法的替代方案。再次感谢。 - user2276091

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接