다음을 통해 공유


RealTimeStylus 잉크 컬렉션 샘플

이 애플리케이션은 RealTimeStylus 클래스를 사용할 때 잉크 컬렉션 및 렌더링을 보여 줍니다.

InkCollection 프로젝트

이 샘플은 하나의 프로젝트 InkCollection을 포함하는 단일 솔루션으로 구성됩니다. 애플리케이션은 라는 InkCollection단일 클래스를 포함하는 네임스페이스를 정의 InkCollection 합니다. 클래스는 Form 클래스에서 상속되며 IStylusAsyncPlugin 인터페이스를 구현합니다.

namespace InkCollection
{
    public class InkCollection : Form, IStylusAsyncPlugin
    {
        //...
      

InkCollection 클래스는 다양한 잉크 두께를 지정하는 데 사용되는 프라이빗 상수 집합을 정의합니다. 또한 클래스는 RealTimeStylus 클래스, myRealTimeStylus, DynamicRenderer 클래스 및 myDynamicRenderer렌더러 클래스 myRenderer의 프라이빗 인스턴스를 선언합니다. DynamicRenderer는 현재 수집 중인 스트로크를 렌더링합니다. 렌더러 개체인 myRenderer는 이미 수집된 Stroke 개체를 렌더링합니다.

private const float ThinInkWidth = 10;
private const float MediumInkWidth = 100;
private const float ThickInkWidth = 200;

private RealTimeStylus myRealTimeStylus;

private DynamicRenderer myDynamicRenderer;
private Renderer myRenderer;

또한 클래스는 하나 이상의 Cursor 개체에 의해 수집되는 패킷 데이터를 저장하는 데 사용되는 Hashtable 개체 myPackets를 선언합니다. Stylus 개체의 ID 값은 지정된 Cursor 개체에 대해 수집된 패킷 데이터를 고유하게 식별하기 위해 해시 테이블 키로 사용됩니다.

Ink 개체 myInk의 프라이빗 instance 에서 수집한 Stroke 개체를 myRealTimeStylus저장합니다.

private Hashtable myPackets;
        
private Ink myInk;

양식 로드 이벤트

양식 myDynamicRenderer 에 대한 Load 이벤트 처리기에서 는 컨트롤을 인수로 사용하는 DynamicRenderer를 사용하여 인스턴스화되고 myRenderer 인수 없는 생성자로 생성됩니다.

private void InkCollection_Load(object sender, System.EventArgs e)
{
    myDynamicRenderer = new DynamicRenderer(this);
    myRenderer = new Renderer();
    // ...

잉크를 렌더링할 때 DrawingAttributes의 기본값을 사용하므로 myDynamicRenderer 렌더러 인스턴스화 다음에 나오는 주석에 주의하세요. 표준 동작입니다. 그러나 에서 렌더링한 잉크와 다른 모양으로 렌더링된 myDynamicRenderermyRenderer잉크를 제공하려는 경우 에서 myDynamicRendererDrawingAttributes 속성을 변경할 수 있습니다. 이렇게 하려면 애플리케이션을 빌드하고 실행하기 전에 다음 줄의 주석 처리를 제거합니다.

    // myDynamicRenderer.DrawingAttributes.PenTip = PenTip.Rectangle;
    // myDynamicRenderer.DrawingAttributes.Height = (.5F)*MediumInkWidth;
    // myDynamicRenderer.DrawingAttributes.Transparency = 128;

다음으로, 애플리케이션은 스타일러스 알림을 받는 데 사용되는 RealTimeStylus 개체를 만들고 DynamicRenderer 개체를 동기 플러그 인 알림 큐에 추가합니다. 특히 SyncPluginCollectionmyRealTimeStylus 속성에 를 추가합니다myDynamicRenderer.

    myRealTimeStylus = new RealTimeStylus(this, true);

    myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);

그런 다음 양식이 비동기 플러그 인 알림 큐에 추가됩니다. 특히 는 InkCollectionAsyncPluginCollection 속성에 추가됩니다. 마지막으로 및 myRealTimeStylusmyDynamicRenderer 가 사용하도록 설정되고 myPackets 및 myInk가 인스턴스화됩니다.

    myRealTimeStylus.AsyncPluginCollection.Add(this);

    myRealTimeStylus.Enabled = true;
    myDynamicRenderer.Enabled = true;  
      
    myPackets = new Hashtable();
    myInk = new Ink();
}

잉크 색과 크기를 변경하기 위해 메뉴 처리기를 연결하는 것 외에도 인터페이스를 구현하기 전에 한 블록의 코드가 더 필요합니다. 샘플은 폼의 Paint 이벤트를 처리해야 합니다. 이벤트 처리기에서 Paint 이벤트가 발생할 때 Stroke 개체가 수집될 수 있으므로 애플리케이션을 새로 고쳐 myDynamicRenderer 야 합니다. 이 경우 이미 수집된 Stroke 개체의 부분을 다시 그려야 합니다. 정적 렌더러는 이미 수집된 Stroke 개체를 다시 그리는 데 사용됩니다. 이러한 스트로크는 다음 섹션과 같이 그릴 때 배치되므로 Ink 개체에 있습니다.

private void InkCollection_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
{
    myDynamicRenderer.Refresh();

    myRenderer.Draw(e.Graphics, myInk.Strokes);
} 

IStylusAsyncPlugin 인터페이스 구현

샘플 애플리케이션은 DataInterest 속성의 구현에서 수신하는 데 관심이 있는 알림 유형을 정의합니다. 따라서 DataInterest 속성은 RealTimeStylus 개체가 양식에 전달하는 알림을 정의합니다. 이 샘플의 경우 DataInterest 속성은 DataInterestMask 열거형을 통해 스타일러스다운, 패킷, 스타일러스업오류 알림에 대한 관심을 정의합니다.

public DataInterestMask DataInterest
{
    get
    {
        return DataInterestMask.StylusDown |
               DataInterestMask.Packets |
               DataInterestMask.StylusUp |
               DataInterestMask.Error;
    }
}

스타일러스다운 알림은 펜이 디지타이저 표면에 닿을 때 발생합니다. 이 경우 샘플은 Stylus 개체의 패킷 데이터를 저장하는 데 사용되는 배열을 할당합니다. StylusDown 메서드의 StylusDownData가 배열에 추가되고 스타일러스 개체의 Id 속성을 키로 사용하여 배열이 해시 테이블로 삽입됩니다.

public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
    ArrayList collectedPackets = new ArrayList();

    collectedPackets.AddRange(data.GetData());

    myPackets.Add(data.Stylus.Id, collectedPackets);
}

패킷 알림은 펜이 디지타이저 화면에서 이동할 때 발생합니다. 이 경우 애플리케이션은 Stylus 개체의 패킷 배열에 새 StylusDownData를 추가 합니다. 이 작업은 Stylus 개체의 Id 속성을 키로 사용하여 해시 테이블의 스타일러스에 대한 패킷 배열을 검색합니다. 그런 다음 새 패킷 데이터가 검색된 배열에 삽입됩니다.

public void Packets(RealTimeStylus sender, PacketsData data)
{
    ((ArrayList)(myPackets[data.Stylus.Id])).AddRange(data.GetData());
}

StylusUp 알림은 펜이 디지타이저 표면을 떠날 때 발생합니다. 이 알림이 발생하면 샘플은 더 이상 필요하지 않으므로 해시 테이블에서 해시 테이블 제거에서 이 Stylus 개체의 패킷 배열을 검색하고, 새 패킷 데이터를 추가하고, 패킷 데이터 배열을 사용하여 새 Stroke 개체 stroke를 만듭니다.

public void StylusUp(RealTimeStylus sender, StylusUpData data)
{
    ArrayList collectedPackets = (ArrayList)myPackets[data.Stylus.Id];
    myPackets.Remove(data.Stylus.Id);

    collectedPackets.AddRange(data.GetData());

    int[] packets = (int[])(collectedPackets.ToArray(typeof(int)));
    TabletPropertyDescriptionCollection tabletProperties =
        myRealTimeStylus.GetTabletPropertyDescriptionCollection(data.Stylus.TabletContextId);

    Stroke stroke = myInk.CreateStroke(packets, tabletProperties);
    if (stroke != null) 
    {
         stroke.DrawingAttributes.Color = myDynamicRenderer.DrawingAttributes.Color;
         stroke.DrawingAttributes.Width = myDynamicRenderer.DrawingAttributes.Width;
    } 
}

사용자 지정 플러그 인 만들기 사용을 포함하여 RealTimeStylus 클래스의 보다 강력한 사용을 보여 주는 예제는 RealTimeStylus 플러그 인 샘플을 참조하세요.

Microsoft.Ink.Renderer

Microsoft.StylusInput.DynamicRenderer

Microsoft.StylusInput.RealTimeStylus

Microsoft.StylusInput.IStylusAsyncPlugin

스타일러스 입력 액세스 및 조작