Handschrifterkennung in Windows Server 2008 R2

Windows Server 2008 R2 unterstützt die serverseitige Handschrifterkennung. Mit der serverseitigen Erkennung kann ein Server Inhalte von Stifteingaben auf Webseiten erkennen. Dies ist besonders nützlich, wenn Benutzer in einem Netzwerk Begriffe angeben, die mithilfe eines Benutzerwörterbuchs interpretiert werden. Wenn Sie beispielsweise eine medizinische Anwendung haben, die eine Serverdatenbank nach Patientennamen abgefragt hat, könnten diese Namen einer anderen Datenbank hinzugefügt werden, auf die bei Suchvorgängen aus einem handschriftlichen Silverlight-Formular querverwiesen wird.

Einrichten des Servers für Server-Side Erkennung

Die folgenden Schritte sollten ausgeführt werden, um die serverseitige Erkennung einzurichten.

  • Installieren von Freihand- und Handschriftdiensten
  • Installieren der Unterstützung für Webserver (IIS) und Anwendungsserver
  • Aktivieren der Desktopdarstellungsrolle
  • Starten des Tablet-PC-Eingabediensts

Installieren von Freihand- und Handschriftdiensten

Um Freihand- und Handschriftdienste zu installieren, öffnen Sie den Server-Manager, indem Sie in der Schnellstartleiste auf das Server-Manager-Symbol klicken. Klicken Sie im Menü Features auf Features hinzufügen. Stellen Sie sicher, dass Sie das Kontrollkästchen Freihand- und Handschriftdienste aktivieren. Die folgende Abbildung zeigt das Dialogfeld Features auswählen , in dem Freihand- und Handschriftdienste ausgewählt sind.

Dialogfeld
Dialogfeld "Features auswählen" mit aktiviertem Kontrollkästchen "Freihand- und Schreibdienste"

Installationsunterstützung für Webserver (IIS) und Anwendungsserver

Öffnen Sie den Server-Manager wie im ersten Schritt. Als Nächstes müssen Sie die Rollen Webserver (IIS) und Anwendungsserver hinzufügen. Klicken Sie im Menü Rollen auf Rollen hinzufügen. Der Assistent zum Hinzufügen von Rollen wird angezeigt. Klicken Sie auf Weiter. Stellen Sie sicher, dass Anwendungsserver und Webserver (IIS) ausgewählt sind. Die folgende Abbildung zeigt das Dialogfeld Serverrollen auswählen , in dem die Rollen Webserver (IIS) und Anwendungsserver ausgewählt sind.

Dialogfeld
Dialogfeld "Serverrollen auswählen" mit ausgewähltem Webserver (IIS) und Anwendungsserverrollen

Wenn Sie Anwendungsserver auswählen, werden Sie aufgefordert, das ASP.NET Framework zu installieren. Klicken Sie auf die Schaltfläche Erforderliche Features hinzufügen . Nachdem Sie auf Weiter geklickt haben, wird ein Übersichtsdialogfeld angezeigt. Klicken Sie auf Weiter. Das Dialogfeld Rollendienste auswählen sollte jetzt verfügbar sein. Stellen Sie sicher, dass Webserver (IIS) ausgewählt ist. Die folgende Abbildung zeigt das Dialogfeld Rollendienste auswählen mit aktiviertem Webserver (IIS).

Dialogfeld
Dialogfeld "Rollendienste auswählen" mit aktiviertem Webserver (IIS)

Klicken Sie auf Weiter. Ein Übersichtsdialogfeld wird angezeigt. klicken Sie erneut auf Weiter . Nun wird ihnen eine Seite mit Optionen für Rollen für Webserver (IIS) angezeigt. Klicken Sie auf Weiter. Auf der nächsten Seite wird die Schaltfläche Installieren aktiv. Klicken Sie auf Installieren , und Installieren Sie die Unterstützung für Webserver (IIS) und Anwendungsserver.

Aktivieren der Desktopdarstellungsrolle

Klicken Sie zum Aktivieren der Desktopoberfläche auf Start, auf Verwaltung und dann auf Server-Manager. Wählen Sie Dienste hinzufügen und dann den Desktopdarstellungsdienst aus. Die folgende Abbildung zeigt das Dialogfeld Features auswählen , in dem das Desktopdarstellungselement installiert ist.

Dialogfeld
Dialogfeld "Features auswählen" mit ausgewähltem Desktopdarstellungsdienst

Klicken Sie auf Weiter , um die Desktopdarstellung zu installieren.

Starten des Tablet-Diensts

Nachdem Sie den Desktopdarstellungsdienst installiert haben, wird der Tablet-PC-Eingabedienst im Menü Dienste angezeigt. Um auf das Menü Dienste zuzugreifen, klicken Sie auf Start, auf Verwaltung und dann auf Dienste. Klicken Sie zum Starten des Diensts mit der rechten Maustaste auf Tablet PC-Eingabedienst , und klicken Sie dann auf Starten. Die folgende Abbildung zeigt das Menü Dienste , in dem der Tablet-PC-Eingabedienst gestartet wurde.

Menü
Menü "Dienste" mit gestartetem Eingabedienst für Tablet-PCs

Ausführen der Server-Side Erkennung mithilfe von Silverlight

In diesem Abschnitt wird gezeigt, wie Sie eine Webanwendung erstellen, die Silverlight zum Erfassen von Handschrifteingaben verwendet. Führen Sie die folgenden Schritte aus, um die Erkennung in Visual Studio 2008 zu programmieren.

  • Installieren und aktualisieren Sie Visual Studio 2008, um Unterstützung für Silverlight hinzuzufügen.
  • Erstellen Sie ein neues Silverlight-Projekt in Visual Studio 2008.
  • Fügen Sie ihrem Projekt die erforderlichen Dienstverweise hinzu.
  • Erstellen Sie einen Silverlight WCF-Dienst für die Freihanderkennung.
  • Fügen Sie dem Clientprojekt den Dienstverweis hinzu.
  • Fügen Sie die InkCollector-Klasse dem InkRecognition-Projekt hinzu.
  • Entfernen von Anweisungen für den sicheren Transport aus der Clientkonfiguration

Installieren und Aktualisieren von Visual Studio 2008, um Unterstützung für Silverlight hinzuzufügen

Bevor Sie beginnen, müssen Sie die folgenden Schritte auf Ihrem Windows Server 2008 R2-Server ausführen.

Nachdem Sie diese Anwendungen und Updates installiert haben, können Sie Ihre serverseitige Erkennungswebanwendung erstellen.

Erstellen eines neuen Silverlight-Webprojekts in Visual Studio 2008

Klicken Sie im Menü Datei auf Neues Projekt. Wählen Sie in der Visual C#-Projektliste die Vorlage Silverlight-Anwendung aus. Nennen Sie Ihr Projekt InkRecognition, und klicken Sie auf OK. Die folgende Abbildung zeigt das ausgewählte C#-Silverlight-Projekt mit dem Namen InkRecognition.

Ausgewähltes c#-Silverlight-Projekt mit dem Namen inkrecognition
Ausgewähltes c#-Silverlight-Projekt mit dem Namen inkrecognition

Nachdem Sie auf OK geklickt haben, werden Sie in einem Dialogfeld aufgefordert, Ihrem Projekt eine Silverlight-Anwendung hinzuzufügen. Wählen Sie Hinzufügen eines neuen ASP.NET Webprojekts zur Projektmappe zum Hosten von Silverlight aus, und klicken Sie auf OK. Die folgende Abbildung zeigt, wie Sie das Beispielprojekt einrichten, bevor Sie auf OK klicken.

Dialogfeld mit Aufforderung zum Hinzufügen einer Silverlight-Anwendung zu einem Projekt
Dialogfeld mit Aufforderung zum Hinzufügen einer Silverlight-Anwendung zu einem Projekt

Hinzufügen der erforderlichen Dienstverweise zu Ihrem Projekt

Jetzt haben Sie Ihr generisches Silverlight-Clientprojekt (InkRecognition) mit einem Webprojekt (InkRecognition.Web) in Ihrer Projektmappe eingerichtet. Das Projekt wird geöffnet, wobei Page.xaml und Default.aspx geöffnet sind. Schließen Sie diese Fenster, und fügen Sie dem InkRecognition-Projekt die Verweise System.Runtime.Serialization und System.ServiceModel hinzu, indem Sie mit der rechten Maustaste auf den Ordner verweise im InkRecognition-Projekt klicken und Verweis hinzufügen auswählen. Die folgende Abbildung zeigt das Dialogfeld mit den ausgewählten erforderlichen Verweisen.

Dialogfeld
Dialogfeld "Verweise hinzufügen" mit ausgewählter Option "system.runtime.serialization" und "system.servicemodel"

Als Nächstes müssen Sie dem Projekt InkRecognition.Web die Verweise System.ServiceModel und Microsoft.Ink hinzufügen. Der Microsoft.Ink-Verweis wird in den .NET-Verweisen standardmäßig nicht angezeigt. Suchen Sie daher in Ihrem Windows-Ordner nach Microsoft.Ink.dll. Nachdem Sie die DLL gefunden haben, fügen Sie die Assembly den Projektverweisen hinzu: Wählen Sie die Registerkarte Durchsuchen aus, wechseln Sie zu dem Ordner mit Microsoft.Ink.dll, wählen Sie Microsoft.Ink.dll aus, und klicken Sie dann auf OK. Die folgende Abbildung zeigt die Projektmappe in Windows Explorer mit allen hinzugefügten Verweisassemblys.

Inkrecognition-Projekt im Windows-Explorer mit allen hinzugefügten Verweisassemblys
Inkrecognition-Projekt im Windows-Explorer mit allen hinzugefügten Verweisassemblys

Erstellen eines Silverlight-WCF-Diensts für die Freihanderkennung

Als Nächstes fügen Sie dem Projekt einen WCF-Dienst für die Freihanderkennung hinzu. Klicken Sie mit der rechten Maustaste auf Ihr InkRecognition.Web-Projekt, klicken Sie auf Hinzufügen, und klicken Sie dann auf Neues Element. Wählen Sie die Vorlage WCF Silverlight-Dienst aus, ändern Sie den Namen in InkRecogitionService, und klicken Sie dann auf Hinzufügen. Die folgende Abbildung zeigt das Dialogfeld Neues Element hinzufügen , in dem der Silverlight-WCF-Dienst ausgewählt und benannt ist.

Dialogfeld
Dialogfeld "Neues Element hinzufügen" mit ausgewähltem und benanntem Silverlight-Wcf-Dienst

Nachdem Sie den WCF Silverlight-Dienst hinzugefügt haben, wird der Dienstcode hinter InkRecognitionService.cs geöffnet. Ersetzen Sie den Dienstcode durch den folgenden Code.

using System;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Activation;
using System.Collections.Generic;
using System.Text;
using Microsoft.Ink;

namespace InkRecognition.Web
{
    [ServiceContract(Namespace = "")]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
    public class InkRecognitionService
    {
        [OperationContract]
        public string[] Recognize(int[][] packets)
        {
            // Deserialize ink.
            Ink ink = new Ink();
            Tablet tablet = new Tablets().DefaultTablet;
            TabletPropertyDescriptionCollection desc = new TabletPropertyDescriptionCollection();
            desc.Add(new TabletPropertyDescription(PacketProperty.X, tablet.GetPropertyMetrics(PacketProperty.X)));
            desc.Add(new TabletPropertyDescription(PacketProperty.Y, tablet.GetPropertyMetrics(PacketProperty.Y)));
            int numOfStrokes = packets.GetUpperBound(0) + 1;
            for (int i = 0; i < numOfStrokes; i++)
            {
                ink.CreateStroke(packets[i], desc);
            }

            // Recognize ink.
            RecognitionStatus recoStatus;
            RecognizerContext recoContext = new RecognizerContext();
            recoContext.RecognitionFlags = RecognitionModes.LineMode | RecognitionModes.TopInkBreaksOnly;
            recoContext.Strokes = ink.Strokes;
            RecognitionResult recoResult = recoContext.Recognize(out recoStatus);
            RecognitionAlternates alternates = recoResult.GetAlternatesFromSelection();
            string[] results = new string[alternates.Count];
            for (int i = 0; i < alternates.Count; i++)
            {
                results[i] = alternates[i].ToString();
            }

            // Send results to client.
            return results;
        }
    }
}

Hinzufügen des Dienstverweis zu Ihrem Clientprojekt

Nachdem Sie nun über Ihren Silverlight-WCF-Dienst für InkRecognition verfügen, nutzen Sie den Dienst aus Ihrer Clientanwendung. Klicken Sie mit der rechten Maustaste auf das Projekt InkRecognition, und wählen Sie Dienstverweis hinzufügen aus. Wählen Sie im angezeigten Dialogfeld Dienstverweis hinzufügen die Option Ermitteln aus, um Dienste aus der aktuellen Lösung zu ermitteln. InkRecognitionService wird im Bereich Dienste angezeigt. Doppelklicken Sie im Bereich Dienste auf InkRecognitionService, ändern Sie den Namespace in InkRecognitionServiceReference, und klicken Sie dann auf OK. Die folgende Abbildung zeigt das Dialogfeld Dienstverweis hinzufügen , in dem InkRecognitionService ausgewählt und der Namespace geändert wurde.

Dialogfeld
Dialogfeld "Dienstverweis hinzufügen" mit ausgewählter Option "inkrecognitionservice" und geändertem Namespace

Hinzufügen der InkCollector-Klasse zum InkRecognition-Projekt

Klicken Sie mit der rechten Maustaste auf das Projekt InkRecognition, klicken Sie auf Hinzufügen, und klicken Sie dann auf Neues Element. Wählen Sie im Visual C#- Menü die C#-Klasse aus. Nennen Sie die Klasse InkCollector. Die folgende Abbildung zeigt das Dialogfeld mit ausgewählter und benannter C#-Klasse.

Dialogfeld
Dialogfeld "Neues Element hinzufügen" mit ausgewählter und benannter C#-Klasse

Nachdem Sie die InkCollector-Klasse hinzugefügt haben, wird die Klassendefinition geöffnet. Ersetzen Sie den Code im Freihandsammler durch den folgenden Code.

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace InkRecognition
{
    public class InkCollector : IDisposable
    {
        public InkCollector(InkPresenter presenter)
        {
            _presenter = presenter;
            _presenter.Cursor = Cursors.Stylus;
            _presenter.MouseLeftButtonDown += new MouseButtonEventHandler(_presenter_MouseLeftButtonDown);
            _presenter.MouseMove += new MouseEventHandler(_presenter_MouseMove);
            _presenter.MouseLeftButtonUp += new MouseButtonEventHandler(_presenter_MouseLeftButtonUp);
        }

        void _presenter_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            _presenter.CaptureMouse();
            if (!e.StylusDevice.Inverted)
            {
                _presenter.Cursor = Cursors.Stylus;
                _stroke = new Stroke(e.StylusDevice.GetStylusPoints(_presenter));
                _stroke.DrawingAttributes = _drawingAttributes;
                _presenter.Strokes.Add(_stroke);
            }
            else
            {
                _presenter.Cursor = Cursors.Eraser;
                _erasePoints = e.StylusDevice.GetStylusPoints(_presenter);
            }
        }

        void _presenter_MouseMove(object sender, MouseEventArgs e)
        {
            if (!e.StylusDevice.Inverted)
            {
                _presenter.Cursor = Cursors.Stylus;
            }
            else
            {
                _presenter.Cursor = Cursors.Eraser;
            }
            if (_stroke != null)
            {
                _stroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
            }
            else if (_erasePoints != null)
            {
                _erasePoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
                StrokeCollection hitStrokes = _presenter.Strokes.HitTest(_erasePoints);
                if (hitStrokes.Count > 0)
                {
                    foreach (Stroke hitStroke in hitStrokes)
                    {
                        _presenter.Strokes.Remove(hitStroke);
                    }
                }
            }
        }

        void _presenter_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            _presenter.ReleaseMouseCapture();
            if (_stroke != null)
            {
                _stroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(_presenter));
            }
            _stroke = null;
            _erasePoints = null;
        }

        public DrawingAttributes DefaultDrawingAttributes
        {
            get { return _drawingAttributes; }
            set { _drawingAttributes = value; }
        }

        public void Dispose()
        {
            _presenter.MouseLeftButtonDown -= new MouseButtonEventHandler(_presenter_MouseLeftButtonDown);
            _presenter.MouseMove -= new MouseEventHandler(_presenter_MouseMove);
            _presenter.MouseLeftButtonUp -= new MouseButtonEventHandler(_presenter_MouseLeftButtonUp);
            _presenter = null;
        }

        private InkPresenter _presenter = null;
        private Stroke _stroke = null;
        private StylusPointCollection _erasePoints = null;
        private DrawingAttributes _drawingAttributes = new DrawingAttributes();
    }
}

Aktualisieren des XAML für die Standardseite und Hinzufügen eines CodeBehind für die Handschrifterkennung

Nachdem Sie nun über eine Klasse verfügen, die Freihandeingaben sammelt, müssen Sie den XAML-Code in page.xaml mit dem folgenden XAML-Code aktualisieren. Der folgende Code fügt dem Eingabebereich einen gelben Farbverlauf, ein InkCanvas-Steuerelement und eine Schaltfläche hinzu, die die Erkennung auslöst.

<UserControl x:Class="InkRecognition.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <Grid x:Name="LayoutRoot" Background="White">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Border Margin="5" Grid.Row="0" BorderThickness="4" BorderBrush="Black" CornerRadius="5" Height="200">
            <Grid>
                <InkPresenter x:Name="inkCanvas">
                    <InkPresenter.Background>
                        <LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
                            <GradientStop Offset="0" Color="Yellow"/>
                            <GradientStop Offset="1" Color="LightYellow"/>
                        </LinearGradientBrush>
                    </InkPresenter.Background>
                </InkPresenter>
                <Button Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Bottom" Margin="10" Content="Recognize" Click="RecoButton_Click"/>
            </Grid>
        </Border>
        <Grid Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <TextBlock Grid.Column="0" FontSize="28" Text="Result: "/>
            <ComboBox x:Name="results" Grid.Column="1" FontSize="28"/>
        </Grid>
    </Grid>
</UserControl>

Ersetzen Sie die CodeBehind-Seite Page.xaml.cs durch den folgenden Code, der einen Ereignishandler für die Schaltfläche Erkennen hinzugibt.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using InkRecognition.InkRecognitionServiceReference;

namespace InkRecognition
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            inkCol = new InkCollector(inkCanvas);
            recoClient = new InkRecognitionServiceClient();
            recoClient.RecognizeCompleted += new EventHandler<RecognizeCompletedEventArgs>(recoClient_RecognizeCompleted);
        }

        private void RecoButton_Click(object sender, RoutedEventArgs e)
        {
            // Serialize the ink into an array on ints.
            ObservableCollection<ObservableCollection<int>> packets = new ObservableCollection<ObservableCollection<int>>();
            double pixelToHimetricMultiplier = 2540d / 96d;

            foreach (Stroke stroke in inkCanvas.Strokes)
            {
                packets.Add(new ObservableCollection<int>());
                int index = inkCanvas.Strokes.IndexOf(stroke);
                for (int i = 0; i < stroke.StylusPoints.Count; i += 2)
                {
                    packets[index].Add(Convert.ToInt32(stroke.StylusPoints[i].X * pixelToHimetricMultiplier));
                    packets[index].Add(Convert.ToInt32(stroke.StylusPoints[i].Y * pixelToHimetricMultiplier));
                }
            }

            // Call the Web service.
            recoClient.RecognizeAsync(packets);
        }

        void recoClient_RecognizeCompleted(object sender, RecognizeCompletedEventArgs e)
        {
            // We have received results from the server, now display them.
            results.ItemsSource = e.Result;
            UpdateLayout();
            results.SelectedIndex = 0;
            inkCanvas.Strokes.Clear();
        }

        private InkRecognitionServiceClient recoClient = null;
        private InkCollector inkCol = null;
    }
}

Entfernen von Secure Transport-Direktiven aus der Clientkonfiguration

Bevor Sie den WCF-Dienst nutzen können, müssen Sie alle sicheren Transportoptionen aus der Dienstkonfiguration entfernen, da sichere Transporte in Silverlight 2.0 WCF-Diensten derzeit nicht unterstützt werden. Aktualisieren Sie im Projekt InkRecognition die Sicherheitseinstellungen in ServiceReferences.ClientConfig. Ändern der Sicherheits-XML von

          <security mode="None">
            <transport>
              <extendedProtectionPolicy policyEnforcement="WhenSupported" />
            </transport>
          </security>

zu

       <security mode="None"/>

Jetzt sollte Ihre Anwendung ausgeführt werden. Die folgende Abbildung zeigt, wie die Anwendung innerhalb einer Webseite aussieht, in der eine Handschrift in das Erkennungsfeld eingegeben wurde.

Anwendung innerhalb einerWebseite mit in das Erkennungsfeld eingegebener Handschrift
Anwendung innerhalb einerWebseite mit in das Erkennungsfeld eingegebener Handschrift

Die folgende Abbildung zeigt den erkannten Text in der Dropdownliste Ergebnis .

Anwendung in einerWebpagemit erkanntem Text in der Dropdownliste
Anwendung in einerWebpagemit erkanntem Text in der Dropdownliste "Ergebnis"