Freihandteilerbeispiel
Dieses Beispiel basiert auf dem Beispiel für die Freihandsammlung. Es zeigt, wie Sie das Divider-Objekt verwenden, um Freihandeingaben zu analysieren.
Ausführliche konzeptionelle Informationen zu Divider finden Sie unter The Divider Object.
Wenn das Formular aktualisiert wird, zeichnet das Beispiel ein begrenzungsfähiges Rechteck um jede analysierte Einheit, unterteilt in Wörter, Zeilen, Absätze und Zeichnungen. Neben der Verwendung verschiedener Farben werden diese Rechtecke um verschiedene Mengen vergrößert, um sicherzustellen, dass keines der Rechtecke von anderen verdeckt wird. Die folgende Tabelle gibt die Farbe und Vergrößerung für jede analysierte Einheit an.
analysierte Einheit | Color | Pixelvergrößerung |
---|---|---|
Word |
Grün |
1 |
Linie |
Magenta |
3 |
Paragraph |
Blau |
5 |
Zeichnung |
Red |
1 |
Einrichten des Formulars
Wenn das Formular geladen wird, wird ein Divider-Objekt erstellt. Ein InkOverlay-Objekt wird erstellt und einem Bereich im Formular zugeordnet. Anschließend werden Ereignishandler an das InkOverlay-Objekt angefügt, um nachzuverfolgen, wann Striche hinzugefügt und gelöscht werden. Wenn dann Erkennungen verfügbar sind, wird dem Divider ein RecognizerContext-Objekt für die Standarderkennung zugewiesen. Anschließend wird die LineHeight-Eigenschaft des Divider-Objekts festgelegt, und die Strokes-Auflistung aus dem InkOverlay-Objekt wird dem Divider zugewiesen. Schließlich ist das InkOverlay-Objekt aktiviert.
// 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;
Die Strokes-Auflistung des Divider-Objekts muss mit der Strokes-Auflistung des InkOverlay-Objekts synchronisiert werden (zugriff über die InkOverlay-Eigenschaft des InkOverlay-Objekts). Um sicherzustellen, dass dies geschieht, wird der Stroke-Ereignishandler für das InkOverlay-Objekt wie folgt geschrieben. Beachten Sie, dass der Ereignishandler zuerst testet, ob EditingMode auf Ink festgelegt ist, um Radiererstriche herauszufiltern. Wenn der Benutzer die automatische Layoutanalyse angefordert hat, ruft die Anwendung die DivideInk-Methode des Formulars auf und aktualisiert den Zeichnungsbereich.
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();
}
}
}
Teilen der Freihandeingabe
Wenn der Benutzer im Menü Datei auf Dividieren klickt, wird die Divide-Methode für das Divider-Objekt aufgerufen. Falls verfügbar, wird die Standarderkennung verwendet.
DivisionResult divResult = myInkDivider.Divide();
Das resultierende DivisionResult-Objekt, auf das von der Variablen divResult
verwiesen wird, wird an die Hilfsfunktion übergeben. getUnitBBBoxes()
Die Hilfsfunktion gibt ein Array von Rechtecken für jeden angeforderten Divisionstyp zurück: Segmente, Linien, Absätze oder Zeichnungen.
myWordBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Segment, 1);
myLineBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Line, 3);
myParagraphBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Paragraph, 5);
myDrawingBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Drawing, 1);
Schließlich wird das Neuzeichnen des Formularbereichs erzwungen, sodass die umgebenden Rechtecke angezeigt werden.
DrawArea.Refresh();
Ergebnisse der Freihandanalyse
In der Hilfsprogrammfunktion wird das DivisionResult-Objekt anhand des vom Aufrufer angeforderten Divisionstyps mithilfe der ResultByType-Methode nach seinen Ergebnissen abgefragt. Die ResultByType-Methode gibt eine DivisionUnits-Auflistung zurück. Jede DivisionUnit in der Auflistung stellt eine Zeichnung, ein einzelnes Erkennungssegment der Handschrift, eine Handschriftzeile oder einen Handschriftblock dar, je nachdem, was beim Aufruf der Hilfsfunktion angegeben wurde.
DivisionUnits units = divResult.ResultByType(divType);
Wenn mindestens eine DivisionUnit vorhanden ist, wird ein Array von Rechtecks erstellt, das ein umgebendes Rechteck pro Einheit enthält. (Die Rechtecke werden durch unterschiedliche Mengen für jeden Einheitstyp aufgeblasen, der in der Vergrößerungsvariablen enthalten ist, um Überschneidungen zu vermeiden.)
// 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
}
Neuzeichnen des Formulars
Wenn die Neuerstellung oben erzwungen wird, wird der folgende Code ausgeführt, um die Begrenzungsrahmen für jede DivisionUnit auf dem Formular um die Freihandeingabe zu zeichnen.
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);
}
}
Schließen des Formulars
Die Dispose-Methode des Formulars entsorgt die Objekte InkOverlay, Divider, RecognizerContext und die im Beispiel verwendete Strokes-Auflistung .