Nous continuons ici à présenter la
programmation d’applications utilisant la technologie Tablet PC. Cet article
nous servira en effet de base pour le développement ultérieur d’un outil
d’indexation et de recherche de fichiers encre numérique.
Comme nous l’avons vu dans l’article précédent,
l'environnement Tablet PC offre de nouvelles possibilités de programmation.
Celles-ci sont disponibles via l'API Tablet PC contenue dans le SDK Tablet PC
téléchargeable à cette adresse :
Après avoir installé cet SDK, nous verrons comment utiliser
l’API Tablet PC en faisant un tour d'horizon de ses différentes classes. Nous
essaierons aussi souvent que possible d'illustrer le comportement de ces classes
par des exemples agrémentés du code nécessaire (en C#).
SDK Tablet PC : de l'installation à la découverte de
l'API
Après avoir installé le SDK, il faut configurer
Visual Studio .Net. Pour cela, lorsque vous créez un projet, il faut ajouter une
référence vers Microsoft.Ink.dll. Allez dans le menu 'Projet' et cliquez sur
'Ajouter une référence…'. Dans l'onglet '.NET' sélectionnez 'Microsoft Tablet PC
API' et validez la boîte de dialogue.
Dans l'explorateur de solutions, vous devriez voir
apparaître 'Microsoft.Ink' dans la liste des références.
Deux nouveaux contrôles sont disponibles grâce
à l'API Tablet PC : InkEdit et InkPicture. Pour les faire
apparaître dans l'onglet 'Windows Forms' de la Boîte à outils, cliquez-droit
dessus, puis choisissez 'Personnaliser la boîte à outils…', sélectionnez
l'onglet 'Composants .NET Framework'. Enfin, cochez les contrôles InkEdit
et InkPicture.
Le développeur peut maintenant utiliser toutes
les classes relatives à la technologie encre numérique. Ces classes, détaillées
par la suite, se regroupent en trois catégories : les classes d'interface, les
classes de gestion de l'encre et les classes liées au recognizer (le
terme recognizer désigne le moteur de la reconnaissance d'écriture
manuscrite).
Remarque : Comme dit dans le précédent article,
il est possible d'installer le SDK Tablet PC sur un ordinateur traditionnel (i.e.
sans Windows Edition Tablet PC). Cependant, nombre de fonctionnalités ne seront
pas disponibles, notamment la reconnaissance d'écriture, et il conviendra de
placer du code de déroutement des erreurs lors de l'utilisation de ces
fonctionnalités.
Deux nouveaux contrôles : InkEdit et InkPicture
InkEdit
Ce contrôle dérive du contrôle RichTextBox.
La grande différence est qu'il permet de capturer de l'encre numérique, et de la
convertir au moyen d'un recognizer. Cette conversion peut être
automatique (après un cours délai) ou lancée manuellement. Le texte saisi avec
le stylet est alors entièrement converti en caractères. Cela est très pratique
lorsque l'utilisateur souhaite remplir directement (sans le Panneau de saisie)
des champs (d'un formulaire…) à l'aide de son stylet.
Il permet également la saisie de texte au
clavier, ce qui est très commode lors d'une saisie classique au clavier.
InkPicture
Ce contrôle permet de capturer de l'encre
numérique (notes ou schémas). Il n'y a pas de reconnaissance d'écriture. On peut
également y afficher un bitmap, sur lequel on pourra écrire. Il est donc très
utile pour l'affichage de l'encre numérique 'brute', lorsqu'il n'y a aucun
traitement à effectuer.
Il est à noter que son utilisation sur une
machine non Tablet PC est possible seulement si le SDK Tablet PC y est installé.
Voici enfin une première application Tablet PC,
qui présente ces deux contrôles. Le code est téléchargeable
ici.
Cette application a pour but d’illustrer les
différentes utilisations que l’on peut faire des deux contrôles précédents. Il y
a un InkEdit avec reconnaissance manuelle ou automatique, et un
InkPicture sur lequel on peut afficher le bitmap de son choix et où l’on
peut dessiner :
La construction des objets InkEdit et
InkPicture se fait de manière traditionnelle :
-déclaration dans la classe :
private
Microsoft.Ink.InkEdit inkEdit1;
private
Microsoft.Ink.InkPicture inkPicture1;
-construction :
this.inkEdit1
= new Microsoft.Ink.InkEdit();
this.inkPicture1
= new Microsoft.Ink.InkPicture();
L’initialisation
(taille, position, couleur, label…) se fait de manière totalement identique à
celle des contrôles classiques. Le changement de couleur de l’encre du
InkPicture se fait par :
Le passage de la
reconnaissance automatique à manuelle se fait au moyen de la propriété
RecoTimeout de l’objet InkEdit. Cette propriété fixe le délai de la
reconnaissance automatique (en millisecondes) ; lorsqu’elle est mise à zéro, la
reconnaissance est manuelle :
// charge et affiche
le bitmap de fond du Inkpicture
//
avec gestion des exceptions
bmpFond =
new Bitmap(bmpDlg.FileName);
this.inkPicture1.Size = bmpFond.Size;
inkPicture1.BackgroundImage = bmpFond;
inkPicture1.Ink.DeleteStrokes();
}
}
catch(System.ArgumentException
err)
{
MessageBox.Show ("Le fichier image spécifié
est introuvable", "Fichier introuvable",
MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
Notez la ligne :
inkPicture1.Ink.DeleteStrokes();
qui permet d’effacer à l’ouverture d’un nouveau bitmap
l’encre contenu dans l’InkPicture.
Vous pouvez donc constater que l’utilisation de
ces contrôles est assez simple et ressemble énormément à l’utilisation des
contrôles classiques. Nous allons maintenant voir les classes de la ‘Managed
API’, ensemble de classes qui permettent une gestion beaucoup plus souple de
l’encre numérique.
Les classes d’entrée
Ces classes gèrent la saisie de l’encre et la
gestion des moyens de pointage (souris, stylet…).
Classe Tablet (et collection Tablets)
Cette classe représente un dispositif de
pointage qui reçoit les événements et messages liés à ce dispositif. Il permet
également d’accéder aux différentes propriétés de ce dispositif : par exemple,
les possibilités hardware (intégré ou non à l’écran, l’élément de pointage
doit-il être en contact avec l’écran pour pouvoir renvoyer sa position…).
La collection Tablets liste tous les
dispositifs de pointage présents.
Classes Cursor et CursorButton (et collection
Cursors)
La classe Cursor représente une
extrémité active du stylet (un stylet peut avoir une extrémité encre et une
autre gomme). Chaque objet Cursor possède un ensemble de propriétés
telles que son Id et ses attributs de dessin. Sa propriété Tablet
retourne le dispositif auquel il est rattaché. Il peut posséder par ailleurs un
ensemble de CursorButton que l’on accède par la propriété Buttons.
Ces CursorButton, associés chacun à un bouton du stylet, permettent entre
autre de connaître l’état du bouton (invalidé, enfoncé ou relâché).
La collection Cursors liste tous les
extrémités de stylet disponibles (un Tablet PC peut accepter plusieurs stylets
avec plusieurs extrémités).
Classes InkOverlay et InkCollector
Ces deux classes permettent de collecter de
l’encre numérique et de la gérer. Il est possible à la construction de les
attacher à une fenêtre (généralement un Panel, mais pourquoi pas à un
bouton ou à un label ?) en précisant le handle de cette fenêtre. Cela permettra
par la suite de pouvoir dessiner dans cette fenêtre.
InkCollector est un sous ensemble de
InkOverlay : tout ce que peut faire un InkCollector, un InkOverlay
le fait également. A l’inverse du InkOverlay, le InkCollector n’a
pas d’objet Selection ; il ne peut donc pas manipuler les Stroke
sélectionnés.
Enfin, chacun d’eux possède un objet Ink
qui permet de sauvegarder, charger les fichiers encre numérique, d’exécuter la
reconnaissance via sa propriété Strokes…
Toutes les instances de InkCollector
pourront donc toujours être remplacés par des InkOverlay.
Pour exemple, voilà comment on crée un InkOverlay :
private Microsoft.Ink.InkOverlay
inkoverlay1;
inkoverlay1 = new Microsoft.Ink.InkOverlay(panel1.Handle);
inkoverlay1.Enabled = true;
Les classes de 'management'
Classe DrawingAttributes
Cette classe permet d’obtenir et de changer les
options de dessin à partir des classes InkCollector et InkOverlay
(propriété DefaultDrawingAttributes), ou Cursor (propriété
DrawingAttributes). On peut par exemple jouer sur la couleur, la
transparence, la pression et le type d’interaction avec la couleur du fond.
Nous pouvons maintenant présenter un exemple de
programme utilisant les fonctionnalités offertes par les classes InkOverlay,
Cursor(s) et DrawingAttributes. Le code complet est
disponible
ici. Dans cette application, chaque curseur écrit avec des attributs de
dessin (couleur et taille) différents.
Un InkOverlay est créé et attaché à un
Panel. On déclare un événement :
this.inkoverlay1.CursorInRange
+= new
InkCollectorCursorInRangeEventHandler(CursorInRange_Event);
Cet événement correspond à l’entrée d’un Cursor dans
la zone du InkOverlay. Deux cas peuvent amener à cet événement :
-le pointeur de la souris entre dans la zone.
-le pointeur est déjà présent dans la zone mais c’est un
nouveau curseur qui s’approche.
Cet événement est indispensable pour la gestion des
Cursor. En effet, un nouvel objet Cursor est instancié à chaque
apparition d’un nouveau curseur remplissant ainsi la collection Cursors
(cette collection est vide au départ et génère une exception en cas de tentative
d’accès à un Cursor). Dans notre exemple (une souris et un stylet double
extrémité), la collection Cursors contiendra au final trois objets
Cursor, chacun faisant l’objet de traitements différents :
myDrawingAttributes =
new Microsoft.Ink.DrawingAttributes();
// Traitements différents en fonction de l'ID du curseur entrant (e.Cursor)
switch (e.Cursor.Id)
{
// Cas de la
souris
case 1:
myDrawingAttributes.Color = Color.Red;
myDrawingAttributes.Width = 150;
break;
// Cas de
l'extrémité "Ecriture" du stylet
case 2:
myDrawingAttributes.Color = Color.Green;
myDrawingAttributes.Width = 10;
break;
// Cas de
l'extrémité "Gomme" du stylet
case 3:
myDrawingAttributes.Color = Color.Black;
myDrawingAttributes.Width = 50;
break;
}
// Attachement des
attributs nouvellement définis au curseur
e.Cursor.DrawingAttributes =
myDrawingAttributes;
}
On peut noter ici que si le Cursor actif ne s’est
pas vu attaché de DrawingAttributes, c’est le DefaultDrawingAttributes
du InkOverlay qui sera utilisé.
Remarque : il conviendrait de ne pas implémenter en dur la
liste des Cursor présents sur le Tablet PC mais d’utiliser la collection
Tablets.
Classes Stroke (et Strokes)
La classe Stroke représente l’objet créé
lorsque l’on dessine un trait sans lever le stylet. Elle permet de manipuler ce
trait (déplacement, rotation, effacement…) et d’accéder à des propriétés telles
que le nombre de points, l’ID, le statut (s’il est affiché ou s’il a été
effacé). L’objet Strokes est une collection de Stroke. Il permet
d’appliquer des traitements communs à tous les Stroke qu’il référence.
Classe Ink
Cette classe représente l’objet englobant une
collection Strokes. Elle permet entre autre le chargement et la
sauvegarde d’un fichier encre numérique (via un buffer). Le code ci-après montre
comment effectuer ces deux actions :
Elle permet de copier et de coller l’ensemble des Stroke
vers le Presse-papier.
Les classes de reconnaissance
RecognitionAlternate (et collection
RecognitionAlternates)
Cette classe représente le résultat d’une
reconnaissance appliquée à une collection Strokes. Elle contient le texte
reconnu accessible via la méthode ToString(), le niveau de confiance dans
le mot reconnu (seulement pour le Recognizer en anglais), le nombre de
lignes du résultat…
RecognitionAlternates est une collection
de RecognitionAlternate.
RecognitionResult
Cette classe représente tous les résultats
possibles renvoyés par une reconnaissance. Il contient la collection
RecognitionAlternates renvoyée, ainsi que le résultat bénéficiant de la plus
grande confiance (propriété TopAlternate).
Recognizer (et collection Recognizers)
Un Recognizer représente l’objet
effectuant la reconnaissance. On peut par exemple accéder via ses propriétés aux
langues reconnues. Tous les champs d’un Recognizer sont en lecture seule.
Une collection Recognizers liste tous
les Recognizer disponibles et indique le Recognizer par défaut.
WordList
Un objet de type WordList est une liste
de mots que l’on peut créer et qui sert à améliorer la reconnaissance. Elle sert
surtout à constituer un dictionnaire personnel. La méthode Add(string word)
permet de remplir cette liste.
Voici un exemple mettant en œuvre l’édition des Stroke
ainsi que la reconnaissance. Le code intégral est disponible
ici.
Concernant les Stroke, lorsque
l’utilisateur change la ComboBox, le mode d’édition des Stroke est
changé :
Le changement de couleur se fait au moyen de la propriété
DefaultDrawingAttributes du InkOverlay (les DrawingAttributes
des différents Cursor n’ayant pas été définis comme dans l’exemple
précédent) :
Concernant la reconnaissance, nous avons choisi
la méthode lourde mais plus paramétrable et plus parlante. En effet, il existe
la méthode ToString() de l’objet InkOverlay.Strokes qui permet
d’obtenir directement le résultat de la reconnaissance.
Ici, nous instancions un objet Recognizer que nous
initialisons au Recognizer par défaut. Puis, nous créons un
RecognizerContext à partir de ce dernier :
// Récupération du recognizer par
défaut (francais) et création d'un contexte
Ensuite, nous créons une WordList que nous
remplissons. Nous la rattachons au RecognizerContext puis forçons la
prise en compte de cette liste lors des prochaines reconnaissances :
Microsoft.Ink.WordList myWordList
= new WordList();
myWordList.Add("Frodon");
myWordList.Add("Gandalf");
…
// Attachement de la liste
de mots au contexte
myRecoContext.WordList = myWordList;
// Permet l'utilisation de
la liste de mots
myRecoContext.Factoid = Factoid.WordList;
Il est possible de durcir cette prise en compte en imposant
que la reconnaissance se fasse uniquement à partir de cette liste :
Il faut ensuite récupérer le Strokes sur lequel va
se faire la reconnaissance. Cette action doit impérativement être réalisée
après le rattachement de la WordList et le paramétrage du Factoid :
myRecoContext.Strokes = inkO1.Selection;
Il ne reste plus qu’à créer un RecognitionStatus et
un RecognitionResult pour stocker respectivement les erreurs éventuelles
de la reconnaissance et le résultat. On lance la reconnaissance par la méthode
Recognize(out RecognitionStatus recognitionStatus) :
RecognitionStatus myRecoStatus;
RecognitionResult myResult;
// Récupération du
résultat de la reconnaissance
// Stockage du code d'une
ereur éventuelle dans myRecoStatus
Finalement, l’application présentée permet de tester dans
les grandes lignes la gestion des Stroke ainsi que la reconnaissance de
caractères.
Conclusion
Lors de la conception d’une application, le
développeur peut choisir entre InkControl et Managed API selon la
destination du produit. En effet, les InkControl sont pratiques lorsque
l’application n’a pas pour objet la manipulation de l’encre numérique. Ils
permettent de développer une application destinée à la fois aux Tablet PC et aux
ordinateurs de bureau. En revanche, la Managed API offre une interface de
gestion de l’encre numérique plus fine.
En Savoir Plus
Evaluez cet article
Pour afficher ou poster un commentaire, cliquez sur ce lien : Forum-Microsoft
Retrouvez ci-dessous les autres sections du Laboratoire Microsoft