Exemple de séparateur d’encre
Cet exemple est basé sur l’exemple de collection d’encre. Il montre comment utiliser l’objet Divider pour analyser l’entrée manuscrite.
Pour obtenir des informations conceptuelles détaillées sur divider, consultez L’objet Divider.
Lorsque le formulaire est mis à jour, l’exemple dessine un rectangle englobant autour de chaque unité analysée, divisé en mots, lignes, paragraphes et dessins. En plus d’utiliser différentes couleurs, ces rectangles sont agrandis de différentes quantités pour garantir qu’aucun des rectangles n’est masqué par d’autres. Le tableau suivant spécifie la couleur et l’agrandissement de chaque unité analysée.
unité analysée | Color | Agrandissement des pixels |
---|---|---|
Word |
Vert |
1 |
Courbes |
Magenta |
3 |
Paragraph |
Bleu |
5 |
Dessin |
Rouge |
1 |
Configuration du formulaire
Lorsque le formulaire se charge, un objet Divider est créé. Un objet InkOverlay est créé et associé à un panneau dans le formulaire. Ensuite, les gestionnaires d’événements sont attachés à l’objet InkOverlay pour suivre quand des traits sont ajoutés et supprimés. Ensuite, si des modules de reconnaissance sont disponibles, un objet RecognizerContext pour le module de reconnaissance par défaut est affecté au séparateur. Ensuite, la propriété LineHeight de l’objet Divider est définie et la collection Strokes de l’objet InkOverlay est affectée au Séparateur. Enfin, l’objet InkOverlay est activé.
// Create the ink overlay and associate it with the form
myInkOverlay = new Microsoft.Ink.InkOverlay(DrawArea.Handle);
// Set the erasing mode to stroke erase.
myInkOverlay.EraserMode = InkOverlayEraserMode.StrokeErase;
// Hook event handler for the Stroke event to myInkOverlay_Stroke.
// This is necessary since the application needs to pass the strokes
// to the ink divider.
myInkOverlay.Stroke += new InkCollectorStrokeEventHandler(myInkOverlay_Stroke);
// Hook the event handler for StrokeDeleting event to myInkOverlay_StrokeDeleting.
// This is necessary as the application needs to remove the strokes from
// ink divider object as well.
myInkOverlay.StrokesDeleting += new InkOverlayStrokesDeletingEventHandler(myInkOverlay_StrokeDeleting);
// Hook the event handler for StrokeDeleted event to myInkOverlay_StrokeDeleted.
// This is necessary to update the layout analysis result when automatic layout analysis
// option is selected.
myInkOverlay.StrokesDeleted += new InkOverlayStrokesDeletedEventHandler(myInkOverlay_StrokeDeleted);
// Create the ink divider object
myInkDivider = new Divider();
// Add a default recognizer context to the divider object
// without adding the recognizer context, the divider would
// not use a recognizer to do its word segmentation and would
// have less accurate results.
// Adding the recognizer context slows down the call to
// myInkDivider.Divide though.
// It is possible that there is no recognizer installed on the
// machine for this language. In that case the divider does
// not use a recognizer to improve its accuracy.
// Get the default recognizer if any
try
{
Recognizers recognizers = new Recognizers();
myInkDivider.RecognizerContext = recognizers.GetDefaultRecognizer().CreateRecognizerContext();
}
catch (InvalidOperationException)
{
//We are in the case where no default recognizers can be found
}
// The LineHeight property helps the InkDivider distinguish between
// drawing and handwriting. The value should be the expected height
// of the user's handwriting in ink space units (0.01mm).
// Here we set the LineHeight to 840, which is about 1/3 of an inch.
myInkDivider.LineHeight = 840;
// Assign ink overlay's strokes collection to the ink divider
// This strokes collection is updated in the event handler
myInkDivider.Strokes = myInkOverlay.Ink.Strokes;
// Enable ink collection
myInkOverlay.Enabled = true;
La collection Strokes de l’objet Divider doit être synchronisée avec la collection Strokes de l’objet InkOverlay (accessible via la propriété InkOverlay de l’objet Ink). Pour vous assurer que cela se produit, le gestionnaire d’événements Stroke pour l’objet InkOverlay est écrit comme suit. Notez que le gestionnaire d’événements teste d’abord si EditingMode est défini sur Ink pour filtrer les traits de gomme. Si l’utilisateur a demandé une analyse automatique de la disposition, l’application appelle la méthode DivideInk du formulaire et actualise la zone de dessin.
private void myInkOverlay_Stroke(object sender, InkCollectorStrokeEventArgs e )
{
// Filter out the eraser stroke.
if(InkOverlayEditingMode.Ink == myInkOverlay.EditingMode)
{
// Add the new stroke to the ink divider's strokes collection
myInkDivider.Strokes.Add(e.Stroke);
if(miAutomaticLayoutAnalysis.Checked)
{
// Call DivideInk
DivideInk();
// Repaint the screen to reflect the change
DrawArea.Refresh();
}
}
}
Division de l’encre
Lorsque l’utilisateur clique sur Diviser dans le menu Fichier, la méthode Divide est appelée sur l’objet Divider . Le module de reconnaissance par défaut est utilisé, s’il est disponible.
DivisionResult divResult = myInkDivider.Divide();
L’objet DivisionResult résultant, référencé par la variable divResult
, est passé à une fonction utilitaire, getUnitBBBoxes()
. La fonction utilitaire retourne un tableau de rectangles pour le type de division demandé : segments, lignes, paragraphes ou dessins.
myWordBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Segment, 1);
myLineBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Line, 3);
myParagraphBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Paragraph, 5);
myDrawingBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Drawing, 1);
Enfin, le panneau de formulaire est forcé à redessiner afin que les rectangles englobants apparaissent.
DrawArea.Refresh();
Résultats de l’analyse manuscrite
Dans la fonction utilitaire, l’objet DivisionResult est interrogé pour ses résultats à l’aide de la méthode ResultByType , en fonction du type de division demandé par l’appelant. La méthode ResultByType retourne une collection DivisionUnits . Chaque DivisionUnit de la collection représente un dessin, un seul segment de reconnaissance de l’écriture manuscrite, une ligne d’écriture manuscrite ou un bloc d’écriture manuscrite, selon ce qui a été spécifié lors de l’appel de la fonction utilitaire.
DivisionUnits units = divResult.ResultByType(divType);
S’il existe au moins une DivisionUnit, un tableau de rectangles est créé contenant un rectangle englobant par unité. (Les rectangles sont gonflés par des quantités différentes pour chaque type d’unité, contenues dans la variable de gonflage, afin d’éviter les chevauchements.)
// If there is at least one unit, we construct the rectangles
if((null != units) && (0 < units.Count))
{
// We need to convert rectangles from ink units to
// pixel units. For that, we need Graphics object
// to pass to InkRenderer.InkSpaceToPixel method
using (Graphics g = DrawArea.CreateGraphics())
{
// InkSpace to Pixel Space conversion setup done here.
// Not shown for brevity.
// Iterate through the collection of division units to obtain the bounding boxes
foreach(DivisionUnit unit in units)
{
// Get the bounding box of the strokes of the division unit
divRects[i] = unit.Strokes.GetBoundingBox();
// Div unit rect Ink space to Pixel space conversion done here.
// Not shown for brevity.
// Inflate the rectangle by inflate pixels in both directions
divRects[i].Inflate(inflate, inflate);
// Increment the index
++i;
}
} // Relinquish the Graphics object
}
Redessinage du formulaire
Lorsque le redessinage est forcé ci-dessus, le code suivant s’exécute pour peindre les zones englobantes de chaque DivisionUnit sur le formulaire autour de l’encre.
private void DrawArea_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
// Create the Pen used to draw bounding boxes.
// First set of bounding boxes drawn here are
// the bounding boxes of paragraphs.
// These boxes are drawn with Blue pen.
Pen penBox = new Pen(Color.Blue, 2);
// First, draw the bounding boxes for Paragraphs
if(null != myParagraphBoundingBoxes)
{
// Draw bounding boxes for Paragraphs
e.Graphics.DrawRectangles(penBox, myParagraphBoundingBoxes);
}
// Next, draw the bounding boxes for Lines
if(null != myLineBoundingBoxes)
{
// Color is Magenta pen
penBox.Color = Color.Magenta;
// Draw the bounding boxes for Lines
e.Graphics.DrawRectangles(penBox, myLineBoundingBoxes);
}
// Then, draw the bounding boxes for Words
if(null != myWordBoundingBoxes)
{
// Color is Green
penBox.Color = Color.Green;
// Draw bounding boxes for Words
e.Graphics.DrawRectangles(penBox, myWordBoundingBoxes);
}
// Finally, draw the boxes for Drawings
if(null != myDrawingBoundingBoxes)
{
// Color is Red pen
penBox.Color = Color.Red;
// Draw bounding boxes for Drawings
e.Graphics.DrawRectangles(penBox, myDrawingBoundingBoxes);
}
}
Fermeture du formulaire
La méthode Dispose du formulaire supprime les objets InkOverlay, Divider, RecognizerContext et la collection Strokes utilisée dans l’exemple.