As I mentioned in a previous post, this week we released Smart Device Framework 2.1. A new feature in the product that we added to support an new upcoming control (that is currently in the final stages of development before we release a beta) are new Cut, Copy, Paste and Clear events for the OpenNETCF.Windows.Forms.TextBox2 class.
You are probably thinking “who cares what do I need that for?!” Think of a TextBox where you have sensitive information for example a Social Insurance Number, Drivers License Number or Credit Card Number say in a mobile data collection or mobile billing application. You could have a scrupulous person doing a “Copy” (CTRL-C using the input panel) and pasting (CTRL-V again with the input panel) that information into a webpage opened using Internet Explorer Mobile and emailing that to themselves at the end of the day. It may be difficult to do on a 240×320 screen but it can be done (and has happened in one of my first projects I worked on).
So using a more lighthearted example, let’s take a look at creating a NumericTextBox. There are two ways to implement this control. The first one is to modify the window style of a TextBox using the following.
private void SetNumeric()
int style = OpenNETCF.Win32.Win32Window.GetWindowLong(this.Handle, OpenNETCF.Win32.GWL.STYLE);
style |= (int)OpenNETCF.Win32.ES.NUMBER;
OpenNETCF.Win32.Win32Window.SetWindowLong(this.Handle, OpenNETCF.Win32.GWL.STYLE, style);
The problem with this was it *only* accepted numbers. There are some cases where you need a decimal place, but by modifying the TextBox style to ES_NUMBER, all you get is the ability to enter numbers.
The second option is to create your own control and override the OnKeyPress method and enter your custom logic. There are plenty of samples for creating a control like this but there is a great one here on MSDN specifically for the Compact Framework.
One major flaw with this implementation is a user could always paste text into the TextBox and have no control over what is displayed. Using OpenNETCF.Windows.Forms.TextBox2.Paste event allows you to ‘clean’ the pasted text of any unwanted characters. Here are the new events exposed by TextBox2:
// Occurs when a WM_CLEAR message is sent to the textbox
public event CancelEventHandler Clearing;
// Occurs when a WM_COPY message is sent to the textbox
public event CancelEventHandler Copying;
// Occurs when a WM_CUT message is sent to the textbox
public event CancelEventHandler Cutting;
// Occurs when a WM_PASTE message is sent to the textbox
public event CancelEventHandler Pasting;
All events use the CancelEventHandler Delegate which allows you to cancel the whole operation and not allow the WM_* message to flow to the underlying native control. Let’s take a look at implementing this new functionality for the NumericTextBox.
Here is the sample form we will be using to test the new functionality:
We have three ways to set text into the NumericTextBox:
- Using CTRL-C and CTRL-V keys via the Input Panel
- Sending a WM_COPY message to the lower TextBox and then a WM_PASTE to the NumericTextBox
- Setting the Text property of the NumericTextBox
First we have the OnKeyDown event. Here we check to see if a CTRL key is pressed:
//Added this to allow for CTRL keys to be pressed
protected override void OnKeyDown(KeyEventArgs e)
if ((e.Modifiers & (Keys.Control | Keys.Alt)) != 0)
// Let the edit control handle control and alt key combinations
m_isCtrlKey = true;
Next we have the OnKeyPressed event. Here we validate the text being entered:
// Restricts the entry of characters to digits (including hex), the negative sign,
// the decimal point, and editing keystrokes (backspace).
protected override void OnKeyPress(KeyPressEventArgs e)
e.Handled = true;
m_isCtrlKey = false;
Here is our logic to only allow numeric characters and/or decimals, spaces etc.
/// This was originally in OnKeyPress in the MSDN sample but moved
/// here so we can use in the Paste() method
/// <param name=”key”></param>
private bool ValidateKey(char key)
NumberFormatInfo numberFormatInfo = System.Globalization.CultureInfo.CurrentCulture.NumberFormat;
string decimalSeparator = numberFormatInfo.NumberDecimalSeparator;
string groupSeparator = numberFormatInfo.NumberGroupSeparator;
string negativeSign = numberFormatInfo.NegativeSign;
string keyInput = key.ToString();
bool ret = false;
// Digits are OK
ret = true;
else if (keyInput.Equals(decimalSeparator) || keyInput.Equals(groupSeparator) ||
// Decimal separator is OK
ret = true;
else if (key == ‘\b’)
// Backspace key is OK
ret = true;
//else if ((ModifierKeys & (Keys.Control | Keys.Alt)) != 0)
// // Let the edit control handle control and alt key combinations
else if (this.allowSpace && key == ‘ ‘)
ret = true;
private string CleanString(string value)
if (value == null)
StringBuilder sb = new StringBuilder();
for (int x = 0; x < value.Length; x++)
The ValidateKey() method is taken from the MSDN sample. CleanString() method is used by our overridden Text property and our OnPaste override.
public override string Text
value = CleanString(value);
base.Text = value;
protected override void OnPaste(System.ComponentModel.CancelEventArgs e)
//When something is pasted in we need to verify that they are numeric
string pasted = Clipboard2.GetText();
//Insert the char where the cursor currently is
this.Text = this.Text.Insert(this.SelectionStart, CleanString(pasted));
//Optional. Clear the clipboard so it can’t be used anymore
//Optional. Prevent any event handlers from being called
e.Cancel = true;
//Call the base
protected virtual void OnPaste(CancelEventArgs e);
By overriding OnPaste, we now have the ability to get what has been copied into the clipboard using OpenNETCF.Windows.Forms.Clipboard2 and inserting the ‘cleaned’ text into our new NumericTextBox.
Now we have a nice simple way to stop unwanted characters from being pasted into our TextBox2 control and a nice clean way to know when a Clear, Cutting or Copying operation is being done within our control.
Download the full source for the NumericTextBox here and remember you need the Smart Device Framework 2.1 (either Community Edition or Extensions for Visual Studio) for this sample to work.