Since you're apparently using a Custom Control (TextBox derived), some suggestions to handle the User Paste actions and filtering text edits in your Control (the filter part is what you provided, more work is required in this department to make this bullet-proof - not just in relation to error handling).
This Custom Control adds some features to the standard TextBox:
Filters chars handled by OnKeyPress
, allowing cursor movements, Delete an BackSpace (I've added \b
to the filter Regex, I think it was missing).
Filters WM_PASTE
events in 3 different ways, using the PasteAction
Enum, linked to the Public UserPaste
Property, which defines the Control behavior in reaction to a Paste operation (modify as required):
Allow
: a User can paste anything inside the TextBox
Partial
: a User can paste only what the Regex filter allows, the rest is removed
Disallow
: a User cannot paste anything
Has an option to allow Numbers only, at the base class level (no Regex). This is coupled by the feedback provided by the ErrorProvider class.
To allow the partial paste feature, the WndProc
override intercepts WM_PASTE
, filters the Text read from the Clipboard, using the Clipboard.GetText() method (with TextDataFormat.UnicodeText
), then sends a EM_REPLACESEL
message to the edit control, to add the modified Text (to the User, it appears as an actual paste operation).
► base.WndProc()
is not called in any case and the Clipboard is untouched.
→ If you mean to notify a User of the action taken, please don't show a MessageBox in the WndProc method override.
Note: this is a modified version of the Custom Control I've already posted here (with some other methods that may come in handy), for the same exact matter. → If the two questions are actually related, let me know.
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);
}
}