Freigeben über


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 divResultverwiesen 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 .