C# 防止通过复制粘贴在Usercontrol(文本框)上插入特殊字符

C# 防止通过复制粘贴在Usercontrol(文本框)上插入特殊字符,c#,winforms,copy-paste,C#,Winforms,Copy Paste,我必须验证Usercontrol(文本框)是否插入特殊字符。在按键事件中,我使用此代码来处理此问题 OnKeyPress覆盖: 按键时受保护的覆盖无效(按键事件参数e){ 按键(e); 方法预防(e); } MethodToPrevent函数: private void MethodToPrevent(按键eventargs e){ var regex=new regex(@“[^a-zA-Z0-9\s]”); if(regex.IsMatch(e.KeyChar.ToString()){ e

我必须验证Usercontrol(文本框)是否插入特殊字符。在按键事件中,我使用此代码来处理此问题

OnKeyPress覆盖:

按键时受保护的覆盖无效(按键事件参数e){
按键(e);
方法预防(e);
}
MethodToPrevent函数:

private void MethodToPrevent(按键eventargs e){
var regex=new regex(@“[^a-zA-Z0-9\s]”);
if(regex.IsMatch(e.KeyChar.ToString()){
e、 已处理=正确;
}
}
现在这个工作很好。但如果用户复制粘贴带有特殊字符的字符串,则此操作无效。我怎么办

尝试


但无法在此处捕获发件人部分。

实际上,您的代码阻止ctrl键,但不阻止鼠标右键单击并粘贴。也许您可以阻止鼠标右键单击,或者您可以使用TextChanged事件

private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
{
    base.OnKeyPress(e);
    MethodToPrevent(e);
}

private void MethodToPrevent(KeyPressEventArgs e)
{
    var regex = new Regex(@"[^a-zA-Z0-9\s]");
    if (regex.IsMatch(e.KeyChar.ToString()))
    {
        e.Handled = true;
    }
}

// If the user presses the wrong key, it is already blocked with the 
//MethodToPrevent() before the TextChanged().
//it is only prevent mouse right click and paste
private void textBox1_TextChanged(object sender, EventArgs e)
{
    var regex = new Regex(@"[^a-zA-Z0-9\s]");
    if (regex.IsMatch(textBox1.Text.ToString()))
    {
        textBox1.Text = "";
    }
}

由于您显然使用的是自定义控件(TextBox派生),因此有一些建议可用于处理用户粘贴操作和过滤控件中的文本编辑(过滤器部分就是您提供的,该部门需要做更多的工作才能做到这一点,而不仅仅是在错误处理方面)

此自定义控件向标准文本框添加了一些功能:

  • 过滤由
    OnKeyPress
    处理的字符,允许光标移动,删除退格(我已经将
    \b
    添加到过滤器正则表达式中,我认为它丢失了)

  • 使用链接到Public
    UserPaste
    属性的
    PasteAction
    枚举,以3种不同的方式过滤事件,该属性定义了控件对粘贴操作的反应行为(根据需要修改):

    • 允许
      :用户可以在文本框中粘贴任何内容
    • Partial
      :用户只能粘贴正则表达式筛选器允许的内容,其余内容将被删除
    • 禁止
      :用户不能粘贴任何内容
  • 在基类级别(无正则表达式)有一个仅允许数字的选项。这是由类提供的反馈耦合的

  • 为了允许部分粘贴功能,WndProc覆盖截取
    WM_粘贴
    ,使用方法(使用
    TextDataFormat.UnicodeText
    )过滤从剪贴板读取的文本,然后向编辑控件发送消息,以添加修改后的文本(对于用户来说,它显示为实际的粘贴操作)

    base.WndProc()
    在任何情况下都不会被调用,剪贴板也不会被触动。
    → 如果要通知用户所采取的操作,请不要在WndProc方法覆盖中显示MessageBox

    注意:这是我已经发布的自定义控件的一个修改版本(还有一些其他可能很方便的方法),用于同样的事情。→ 如果这两个问题确实相关,请告诉我



    可能尝试使用另一个事件???,但无法在此处捕获发送者部分。如果尝试使用
    OnTextChanged()
    ,则“发送者”是您所在的类,因为它是一个方法重写,并且您必须位于派生类中?…因此,如果您得到一个不需要的字符,您将在其TextChanged事件处理程序中清除控件的整个文本?Sinatr在一条注释中发布了一个链接,指向禁用WM_粘贴的答案。它也可以用于其他用途,例如警告使用r它的粘贴包含不允许的字符。我只是想指定可以使用textchanged事件。此代码的高级版本是在textchanged事件运行时查找并删除不需要的字符。通常,您尝试不在其textchanged事件中更改控件的文本。或者删除整个文本(在TextChanged事件中),如果用户按错键。不确定此代码的高级版本是什么意思。不,如果用户按错键,则在TextChanged()之前,它已被MethodToPrevent()阻止。在这种操作中,其目的是防止内容发生,而不是在内容发生后尝试修补。因此,您要做的是,如果以任何方式输入了不允许的内容,则首先防止文本发生更改。+您假设正则表达式要输入的每个字符都会引发KeyPress事件此外,正如前面提到的,原则上,您应该尽量避免在TextChanged事件中更改控件的文本(是的,我知道,我已经说过了)。
    private void textBox1_KeyPress(object sender, KeyPressEventArgs e)
    {
        base.OnKeyPress(e);
        MethodToPrevent(e);
    }
    
    private void MethodToPrevent(KeyPressEventArgs e)
    {
        var regex = new Regex(@"[^a-zA-Z0-9\s]");
        if (regex.IsMatch(e.KeyChar.ToString()))
        {
            e.Handled = true;
        }
    }
    
    // If the user presses the wrong key, it is already blocked with the 
    //MethodToPrevent() before the TextChanged().
    //it is only prevent mouse right click and paste
    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        var regex = new Regex(@"[^a-zA-Z0-9\s]");
        if (regex.IsMatch(textBox1.Text.ToString()))
        {
            textBox1.Text = "";
        }
    }
    
    using System.ComponentModel;
    using System.Runtime.InteropServices;
    using System.Security.Permissions;
    using System.Text.RegularExpressions;
    using System.Windows.Forms;
    
    [ToolboxItem(true)]
    [DesignerCategory("Code")]
    public class TextBoxEx : TextBox
    {
        private bool m_NumbersOnly = false;
        private Regex regex = new Regex(@"[^a-zA-Z0-9\s\b]", RegexOptions.Compiled);
    
        public TextBoxEx() { }
    
        public enum PasteAction
        {
            Allow,
            Disallow,
            Partial
        }
    
        public PasteAction UserPaste { get; set; }
    
        public override string Text {
            get => base.Text;
            set {
                if (!base.Text.Equals(value)) {
                    base.Text = regex.Replace(value, "");
                }
            }
        }
    
        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 |= NativeMethods.ES_NUMBER;
                }
                else {
                    cp.Style &= ~NativeMethods.ES_NUMBER;
                }
                return cp;
            }
        }
    
        protected override void WndProc(ref Message m)
        {
            switch (m.Msg) {
                case NativeMethods.WM_PASTE:
                    switch (UserPaste) {
                        case PasteAction.Disallow:
                            return;
                        case PasteAction.Partial:
                            string text = Clipboard.GetText(TextDataFormat.UnicodeText);
                            text = regex.Replace(text, "");
                            NativeMethods.SendMessage(this.Handle, NativeMethods.EM_REPLACESEL, 1, text);
                            return;
                        case PasteAction.Allow:
                            break;
                    }
                    break;
            }
            base.WndProc(ref m);
    
        }
    
        private class NativeMethods
        {
            internal const int WM_PASTE = 0x0302;
            internal const int ES_NUMBER = 0x2000;
            internal const int EM_REPLACESEL = 0xC2;
    
            [DllImport("User32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
            internal static extern int SendMessage(IntPtr hWnd, uint uMsg, int wParam, string lParam);
        }
    }