09.01.2013

Replacing Win XP Accessibility Features

How to get the input from a serial port (Real hardware or USB) into an application that only handles keyboard inputs?

Earlier Windows Versions had an accessibility feature, that would allow you to do just that, by handling serial inputs as if they were keystrokes. This feature however was discontinued in more recent Windows versions. (Vista and above)

So a tool was needed, that would provide the functionality described above.

This surely should not be a problem in .NET and as it turns out it is not. Central to this is the "SendKeys.SendWait()" Method, provided in the framework as part of the "System.Windows.Forms" namespace. MSDN-Article
public static void SendWait ( string keys )
This method takes a string and basically posts it to the operating system as a series of keystrokes. There are however a couple of characters that need to be treated specially because they act as control characters to the SendKeys.SendWait() Method. Namely these are: ^, ~, +, %, (, ), [, ]

In order to use the method for arbitrarily defined strings, these characters need to be put into curly brackets. To send a '+' for example you would need to call the method like this:
SendKeys.SendWait("{+}");
I wrote a method to do this kind of reformatting for me:
        public static string Reformat(string original)
        {
            var sb = new StringBuilder();
            foreach (char c in original)
            {
                switch (c)
                {
                    case '+': case '^': case '~': case '%':
                    case '(': case ')': case '[': case ']':
                        sb.AppendFormat("{{{0}}}", c);
                        break;
                    default:
                        sb.Append(c);
                        break;
                }
            }
            return sb.ToString();
        }
Note that this uses the AppendFormat() Method of a StringBuilder. (Namespace "System.Text") To add curly brackets in the "Format" context you have to type double brackets, because the curly bracket itself is used as an escape sequence in format-strings.

The relevant part in the program looks like this:
        /// <summary>
        /// Event thrown whenever the serial port received data
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void PortOnDataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            while (_port.BytesToRead > 0)
            {
                // PostKeys
                var original = _port.ReadExisting();
                // Reformat string to fit SendKeys.SendWait()
                var reformattedString = Reformat(original);
                try
                {
                    SendKeys.SendWait(reformattedString);
                }
                // Handle exception caused if keys are sent to an application
                // not handling keys
                catch(InvalidOperationException)    
                {
                }
            }
        }
I will make the complete project available on Sourceforge. Comments, questions and suggestions are, as always, very welcome.