由于您显然使用的是自定义控件(派生文本框),一些建议来处理您的控件中的用户粘贴操作和过滤文本编辑(过滤器部分是您提供的,这个部门需要做更多的工作这防弹 - 不仅仅是与错误处理有关)。
此自定义控件为标准文本框添加了一些功能:
-
过滤由OnKeyPress 处理的字符,允许光标移动,删除退格(我已将\b 添加到过滤器正则表达式中,我认为它丢失了)。
-
以 3 种不同方式过滤 WM_PASTE 事件,使用链接到公共 UserPaste 属性的 PasteAction 枚举,该属性定义响应粘贴操作的控件行为(修改为必填):
-
Allow:用户可以在 TextBox 中粘贴任何内容
-
Partial:用户只能粘贴正则表达式过滤器允许的内容,其余内容被删除
-
Disallow:用户无法粘贴任何内容
-
在基类级别(无正则表达式)有一个仅允许数字的选项。这与ErrorProvider 类提供的反馈相结合。
为了允许部分粘贴功能,WndProc 覆盖拦截 WM_PASTE,使用 Clipboard.GetText() 方法(使用 TextDataFormat.UnicodeText)过滤从剪贴板读取的文本,然后发送向编辑控件发送EM_REPLACESEL 消息,以添加修改后的文本(对用户而言,它显示为实际的粘贴操作)。
► base.WndProc() 在任何情况下都不会被调用,剪贴板也不会被触及。
→ 如果您要通知用户所采取的操作,请不要在 WndProc 方法覆盖中显示 MessageBox。
注意:这是我已经发布here 的自定义控件的修改版本(还有一些可能派上用场的其他方法),完全相同。 → 如果这两个问题确实相关,请告诉我。
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);
}
}