インク区切り線のサンプル
このサンプルは、 Ink Collection サンプルに基づいています。 この例では、 Divider オブジェクトを使用してインク入力を分析する方法を示します。
区切り線の詳細な概念情報については、「区切りオブジェクト」を参照してください。
フォームが更新されると、サンプルは、分析された各単位の周囲に外接する四角形を描画し、単語、線、段落、および描画に分割します。 異なる色を使用するだけでなく、これらの四角形は異なる量だけ拡大され、どの四角形も他の四角形によって隠されないようにします。 次の表は、分析された各単位の色と拡大を示しています。
分析された単位 | Color | ピクセルの拡大 |
---|---|---|
Word |
[緑] |
1 |
折れ線 |
赤紫 |
3 |
段落 |
青 |
5 |
描画 |
[赤] |
1 |
フォームの設定
フォームが読み込まれると、 Divider オブジェクトが作成されます。 InkOverlay オブジェクトが作成され、フォーム上のパネルに関連付けられます。 その後、イベント ハンドラーが InkOverlay オブジェクトにアタッチされ、ストロークが追加および削除されるタイミングを追跡します。 次に、認識エンジンが使用可能な場合は、既定の認識エンジンの RecognizerContext オブジェクトが分割線に割り当てられます。 次に、Divider オブジェクトの LineHeight プロパティが設定され、InkOverlay オブジェクトの Strokes コレクションが Divider に割り当てられます。 最後に、InkOverlay オブジェクトが有効になります。
// 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;
Divider オブジェクトの Strokes コレクションは、InkOverlay オブジェクトの Strokes コレクション (InkOverlay オブジェクトの Ink プロパティを介してアクセス) と同期している必要があります。 これを確実に行うために、InkOverlay オブジェクトの Stroke イベント ハンドラーは次のように書き込まれます。 イベント ハンドラーは、まず EditingMode が Ink に設定されているかどうかをテストして消しゴム ストロークをフィルター処理することに注意してください。 ユーザーが自動レイアウト分析を要求した場合、アプリケーションはフォームの DivideInk メソッドを呼び出して、描画領域を更新します。
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();
}
}
}
インクの分割
ユーザーが [ファイル] メニューの [分割] をクリックすると、Divide メソッドがDivider オブジェクトで呼び出されます。 使用可能な場合は、既定の認識エンジンが使用されます。
DivisionResult divResult = myInkDivider.Divide();
結果として得られる DivisionResult オブジェクトは、変数 divResult
によって参照され、 getUnitBBBoxes()
ユーティリティ関数 に渡されます。 ユーティリティ関数は、要求された除算の種類 (セグメント、線、段落、または図面) の四角形の配列を返します。
myWordBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Segment, 1);
myLineBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Line, 3);
myParagraphBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Paragraph, 5);
myDrawingBoundingBoxes = getUnitBBoxes(divResult, InkDivisionType.Drawing, 1);
最後に、外接する四角形が表示されるように、フォーム パネルが強制的に再描画されます。
DrawArea.Refresh();
インク分析の結果
ユーティリティ関数では、呼び出し元が要求した除算の種類に基づいて、ResultByType メソッドを使用して DivisionResult オブジェクトの結果を照会します。 ResultByType メソッドは 、DivisionUnits コレクションを返します。 コレクション内の各 DivisionUnit は、ユーティリティ関数が呼び出されたときに指定された内容に応じて、図面、手書きの 1 つの認識セグメント、手書きの行、または手書きのブロックを表します。
DivisionUnits units = divResult.ResultByType(divType);
DivisionUnit が少なくとも 1 つある場合は、1 つの単位に 1 つの外接する四角形を含む四角形の配列が作成されます。 (四角形は、重なり合わないように、インフレ変数に保持されている単位の種類ごとに異なる量だけ拡張されます)。
// 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
}
フォームの再描画
上記で再描画が強制されると、次のコードが実行され、インクの周囲のフォーム上の各 DivisionUnit の境界ボックスが描画されます。
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);
}
}
フォームを閉じる
フォームの Dispose メソッドは、サンプルで使用される InkOverlay、 Divider、 RecognizerContext オブジェクト、 および Strokes コレクションを破棄します。