Determining Ink Capabilities at Runtime

I’ve been asked on a couple of occasions whether or not it is possible to determine if the Tablet PC OS is installed on a system running a .NET application. Typically, this would be beneficial if you were writing an application that wanted to support both ink and non-ink user input. While the InkEdit control included in the Tablet PC SDK does provide a simple way of supporting ink and non-ink input “out-of-the-box”, more complex solutions might wish to dynamically load different types of UI objects.

There is an example of how you might do this over at MSDN. The C# example uses assembly loading and reflection to determine if the Microsoft.Ink assembly is loaded and whether or not ink recognition is available.

Please Welcome The New Microsoft Developer Evangelist for New England – Chris Bowen!

I happened to read Chris Bowen’s latest blog post today. He has accepted the position as Developer Evangelist for Microsoft in the New England district. While Chris follows a legacy of two fantaatic predecessors in Russ Fustino and Thom Robbins, he brings what I feel are the right “ingredients” for success -

  • A deep understanding of Microsoft platforms, tools and technologies;
  • A wealth of experience with the .NET platform;
  • Strong ties to the Microsoft developer community in New England.

I have had the pleasure of knowing Chris for a while, and I am truly pleased for both him and the community.

 

BTW – Chris (much like his predecessors) has a great sense of humor. This “soft skill” goes a long way in my book… ;-)

Club Pocket PC – Boston Meeting: Wednesday, Oct. 18th, 2006

FYI – The next meeting of Club Pocket PC – Boston will be held on Wednesday, October 18th at 6:30 PM at the Microsoft office in Waltham, MA.

Presentations include:

  • FIRST LOOK: Windows Mobile Device Center for Windows Vista. If you are wondering about how your Windows Mobile device will work with the upcoming Windows Vista operating system, this presentaton will give you insight to the successor to ActiveSync.
  • Microsoft SLAM for Windows Mobile Smartphones. Microsoft Research recently launched SLAM (Social/Location/Annotation/Mobile), a concept application for Windows Mobile Smartphone. SLAM is focused o­n social networking with small groups, exchanging conversations and other media. If you are interested in seeing what Microsoft is thinking in the mobile device social networking space, then this demonstration is a must-see.
  • Ink Enabling Applications for Microsoft Windows Tablet PC Edition. Digital ink functionality has always been a cornerstone of the Microsoft Windows XP Tablet PC Edition platform. Surprisingly, however, there has been slower than anticipated release of “ink-enabled” applications. If you are a .NET developer, you may be very surprised to see just how easy it is to provide ink functionality to your users. This presentation will demonstrate the common steps to support digital ink and related tasks.

I will be presenting the ink-enablement session (and working with my “partner in crime” Steven “fyiguy” Hughes on the other presentations as well. As always, it’s a great opportunity to learn and meet other Windows Mobile and mobile technology enthusiasts. Hope to see some of you there!

Speech in 3 Lines of Code with the .NET Framework 3.0 and Windows Vista

To do this, you will need:

1) Windows Vista (prefereably, RC2 or higher). This ships with the .NET Framework 3.0 included.

Perform the following steps in Visual Studio 2005 (C# shown):

  1. Create a new Windows Application project.
  2. Under the project, add a new reference. Select System.Speech from the .NET tab.
  3. Create a Windows Form, and add a button to it. Name the button btnSpeak.
  4. [Code Line 1] Add a reference to the System.Speech.Systhesis namespace using the using keyword.
  5. using System.Speech.Synthesis;
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
  6. [Code Line 2] Create an instance variable for a SpeechSynthesizer object.
  7. private SpeechSynthesizer mySpokenWords = new SpeechSynthesizer();
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }
  8. Create an event handler for the btnSpeak’s Click event.
  9. [Code Line 3] Add the following code to the Click event handler:
  10. mySpokenWords.Speak("Hello World!");
    .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; } .csharpcode, .csharpcode pre { font-size: small; color: black; font-family: consolas, “Courier New”, courier, monospace; background-color: #ffffff; /*white-space: pre;*/ } .csharpcode pre { margin: 0em; } .csharpcode .rem { color: #008000; } .csharpcode .kwrd { color: #0000ff; } .csharpcode .str { color: #006080; } .csharpcode .op { color: #0000c0; } .csharpcode .preproc { color: #cc6633; } .csharpcode .asp { background-color: #ffff00; } .csharpcode .html { color: #800000; } .csharpcode .attr { color: #ff0000; } .csharpcode .alt { background-color: #f4f4f4; width: 100%; margin: 0em; } .csharpcode .lnum { color: #606060; }

 


Compile and run the code. Click on the button and listen to the result.


That’s all there really is to it!


Total Code:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Speech.Synthesis;

namespace SpeakHelloWorld
{
    public partial class Form1 : Form
    {
        private SpeechSynthesizer mySpokenWords = new SpeechSynthesizer();

        public Form1()
        {
            InitializeComponent();
        }

        private void btnSpeak_Click(object sender, EventArgs e)
        {
            mySpokenWords.Speak("Hello World!");
        }
    }
}

.csharpcode, .csharpcode pre
{
font-size: small;
color: black;
font-family: consolas, “Courier New”, courier, monospace;
background-color: #ffffff;
/*white-space: pre;*/
}
.csharpcode pre { margin: 0em; }
.csharpcode .rem { color: #008000; }
.csharpcode .kwrd { color: #0000ff; }
.csharpcode .str { color: #006080; }
.csharpcode .op { color: #0000c0; }
.csharpcode .preproc { color: #cc6633; }
.csharpcode .asp { background-color: #ffff00; }
.csharpcode .html { color: #800000; }
.csharpcode .attr { color: #ff0000; }
.csharpcode .alt
{
background-color: #f4f4f4;
width: 100%;
margin: 0em;
}
.csharpcode .lnum { color: #606060; }

The .NET Framework 3.0 – Taking Things "One Piece At A Time"

I recently spoke at the Software Association of New Hampshire’s annual InfoXchange event on the .NET Framework 3.0. I had approximately 30 minutes to address the topic “What Is the .NET Framework 3.0, and Why Should I Care?”. It reminded me of those essay questions that went something like this -

Describe the American Revolution and it’s impact on geopolitics in 200 words or less. :-)

I found myself facing a really serious challenge here. As I started to think about how much is really in the .NET Framework 3.0, I realized that for many developers, this could be intimidating (especially from an initial impression respective). I wanted to make certain that (given the short timeframe of the presentation and the need to generalize, I could scare off more people than I would help. I found the answer to how I finally approached the situation, thanks to my two small sons (particularly my oldest, six year-old Nicolas).

Nicolas likes to try out puzzles every once in a while. When I say “puzzles”, I mean just that – the classic tabletop x number of pieces board puzzles. As he gets older, he has worked with increasingly complex puzzles. Now, he has (on occasion) opened a puzzle box and poured out the pieces and stared in disbelief at the sheer number of pieces. Usually, his response is “Dad, forget it. This is just gonna be way too hard.” I usually respond with “OK – let’s at a time.” We first find the corner and edge pieces. Then, we group pieces by commonality (perhaps color or imagery). Finally, we focus on one area of the puzzle at a time. Usually, my son ends up saying something like “Wow, Dad! That really wasn’t so hard.”

I realized the other day that the .NET Framework 3.0 is a lot like my son’s puzzles. At first glance, the .NET Framework 3.0 can translate to “A whole lotta new stuff to learn.” Unfortunately, that typically leads to the common fears of all developers (including myself). If the time is taken, however, to look at each of the “components” of the old WinFX (the “new part” of the .NET FW 3.0) individually, the learning curve might surprise you. It certainly did surprise me.

I ended up taking the time in my presentation to break down each of the new technologies in the .NET Framework 3.0, highlighting what functionality is provided and why it might matter to the developer and/or business owner. There are any number of compelling reasons why the .NET FW 3.0 could be of benefit – but I will leave that to another blog post ;-) In the meantime, I strongly encourage you to take some time to look at the .NET FW 3.0 from a “mid-level” perspective. Not too high-level or too low-level, which can be very intimidating. Instead, take things “one piece at a time”.

Using The New Microsoft.Speech Namespace in the .NET Framework 3.0/Vista

I have had the opportunity to work with the new Microsoft.Speech namespace in the .NET Framework 3.0. The short of it – it rocks! Very easy to get started, but a wealth of sophisticated functionality for developers. Of course, you need to be running Vista in order to make this happen. One thing I really liked is the bringing forward of some of the concepts of Microsoft Speech Server and the Speech Application SDK ("SASDK") into the client-side API. Most notable is the whole prompt database concept, allowing for structured interaction with the user. You do not have to use this, however, as the SpeechSynthesizer.Speak() method does allow for the use of any text string to be spoken.

While most of the messaging around the Speech API is focused on accessibility, speech interaction can be useful on the desktop in other situations. Case in point -

My 6 year-old son is in first grade and learning his spelling. He comes home at the beginning of the week with a new list of spelling words to learn. I decided to combine the power of the Tablet PC with the new Speech API. The result was an application that:

1) Allows the user (I would assume an adult) to create lists of words to practice. The list is stored as XML. Multiple lists can be created.
2) Has the user go through each word. The application speaks the word, then the user spells it by writing on the Tablet PC. Once finished, they tap on a big color-coded button to check the spelling.
3) If the answer is correct, the application says so by voice, then provides a little applause. If the answer is worng, the application says so (in a nice and encouraging way), and a little "awww" is played. The user can always try again.
4) At the end, a tally of total words and correctly spelled words is provided.

Total time to develop the application – about 4 hours from concept to realization. Most of the time was spent on UI creation; writing the Tablet PC-specific code and Speech interface was more of a matter of minutes than hours.

I really think there are many more possible uses for the new Speech API. Just think of something you do currently that involves reading. Would a voice interface be nicer or improve productivity? If the answer is even "maybe", then you should check it out.

Windows Mobile Installers and Vista/WMDC

Just a heads up to all of you Windows Mobile application developers -

If you build an installer for your application, be sure that you do *not* hard code your path to ceappmgr.exe in order to copy and install your CAB files. Instead, you should be looking at the registry for the location of ceappmgr.exe first. The registry key is the same as it has been in the past -

HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\CEAPPMGR.EXE

The location of ceappmgr.exe has changed, and (always a possibility) could change again.

I have noticed that some application installs are failing under the new Windows Mobile Device Center ("WMDC"), while others are succeeding. Having used the registry key technique for all of my CAB installs, Imy applications are not experiencing any issues.