이 샘플은 잉크 컬렉션 샘플기반으로합니다. Divider 개체를 사용하여 잉크 입력을 분석하는 방법을 보여줍니다.
Divider대한 자세한 개념 정보는 나누기 개체참조하세요.
폼이 업데이트되면 샘플은 분석된 각 단위 주위에 경계 사각형을 그립니다. 이 단위들은 단어, 선, 단락, 드로잉으로 나누어집니다. 다른 색을 사용하는 것 외에도 이러한 사각형은 다른 사각형에 의해 가려지지 않도록 서로 다른 크기로 확대됩니다. 다음 표에서는 분석된 각 단위의 색과 확대를 지정합니다.
| 분석된 단위 | 색 | 픽셀 확대 |
|---|---|---|
| 단어 |
녹색 |
1 |
| 줄 |
자홍색 |
3 |
| 단락 |
파랑 |
5 |
| 그림 |
빨강 |
1 |
양식 설정
폼이 로드되면 Divider 개체가 만들어집니다. InkOverlay 개체가 생성되어 양식의 패널과 연결됩니다. 그런 다음, 이벤트 처리기가 InkOverlay 개체에 연결되어 스트로크가 추가되고 삭제되는 시기를 추적합니다. 그런 다음 인식기를 사용할 수 있는 경우 기본 인식기의 RecognizerContext 개체가 Divider에 할당됩니다. 그런 다음 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();
}
}
}
잉크 나누기
사용자가 파일 메뉴에서 나누기를 클릭하면 Divider 개체에서 나누기 메서드가 호출됩니다. 사용 가능한 경우 기본 인식기가 사용됩니다.
DivisionResult divResult = myInkDivider.Divide();
divResult변수에서 참조하는 결과 DivisionResult 개체는 유틸리티 함수 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();
잉크 분석 결과
유틸리티 함수에서 DivisionResult 개체는 호출자가 요청한 나누기 형식에 따라 ResultByType 메서드를 사용하여 결과를 쿼리합니다. ResultByType 메서드는 DivisionUnits 컬렉션을 반환합니다. 컬렉션의 각 DivisionUnit 유틸리티 함수가 호출될 때 지정된 항목에 따라 드로잉, 필기 단일 인식 세그먼트, 필기 줄 또는 필기 블록을 나타냅니다.
DivisionUnits units = divResult.ResultByType(divType);
하나 이상의 DivisionUnit이 있는 경우, 각 단위당 하나의 경계 사각형을 포함하는 사각형 배열이 만들어집니다. (사각형은 겹치지 않도록 팽창 변수에 보관된 각 단위 유형에 대해 서로 다른 양으로 팽창됩니다.)
// 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 컬렉션을 삭제합니다.