RealTimeStylus Ink 集合示例

此应用程序演示使用 RealTimeStylus 类时的墨迹收集和呈现。

InkCollection 项目

此示例由包含一个项目 InkCollection 的单个解决方案组成。 应用程序定义 InkCollection 包含单个类的命名空间,也称为 InkCollection。 类继承自 Form 类,并实现 IStylusAsyncPlugin 接口。

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

InkCollection 类定义一组专用常量,用于指定各种墨迹粗细。 类还声明 RealTimeStylus 类、myRealTimeStylusDynamicRenderer 类和 RenderermyRenderermyDynamicRenderer的私有实例。 DynamicRenderer 呈现当前正在收集的笔划。 Renderer 对象 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;

类还声明 一个 Hashtable 对象 , myPackets该对象用于存储由一个或多个 Cursor 对象收集的数据包数据。 Stylus 对象的 Id 值用作哈希表键,以唯一标识为给定 Cursor 对象收集的数据包数据。

Ink 对象的私有实例,myInk存储由 收集的 myRealTimeStylusStroke 对象。

private Hashtable myPackets;
        
private Ink myInk;

窗体加载事件

在窗体的 Load 事件处理程序中, myDynamicRenderer 通过使用将控件作为参数的 DynamicRenderer 实例化,并使用 myRenderer 无参数构造函数进行构造。

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

请注意呈现器实例化后的注释,因为在 myDynamicRenderer 呈现墨迹时使用 DrawingAttributes 的默认值。 这是标准行为。 但是,如果要为呈现myDynamicRenderer的墨迹提供与 呈现myRenderer的墨迹不同的外观,可以更改 上的 myDynamicRendererDrawingAttributes 属性。 为此,请在生成并运行应用程序之前取消注释以下行。

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

接下来,应用程序创建 RealTimeStylus 对象,该对象用于接收触笔通知,并将 DynamicRenderer 对象添加到同步插件通知队列。 具体而言, myRealTimeStylus 将 添加到 myDynamicRendererSyncPluginCollection 属性。

    myRealTimeStylus = new RealTimeStylus(this, true);

    myRealTimeStylus.SyncPluginCollection.Add(myDynamicRenderer);

然后,窗体将添加到异步插件通知队列。 具体而言, InkCollection 添加到 AsyncPluginCollection 属性。 最后, myRealTimeStylus 启用 和 myDynamicRenderer ,并实例化 myPackets 和 myInk。

    myRealTimeStylus.AsyncPluginCollection.Add(this);

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

除了挂接用于更改墨迹颜色和大小的菜单处理程序外,在实现接口之前还需要一个简短的代码块。 该示例必须处理窗体的 Paint 事件。 在事件处理程序中,应用程序必须刷新 myDynamicRenderer ,因为可能在 Paint 事件发生时收集 Stroke 对象。 在这种情况下,需要重新绘制已收集的 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 枚举定义对 StylusDownPacketsStylusUpError 通知的兴趣。

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

当触控笔触摸数字化器表面时,将发出 StylusDown 通知。 发生这种情况时,示例会分配一个数组,该数组用于存储 Stylus 对象的数据包数据。 StylusDown 方法中的 StylusDownData 将添加到数组中,并将该数组插入到哈希表中,方法是使用 Stylus 对象的 Id 属性作为键。

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

    collectedPackets.AddRange(data.GetData());

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

当触控笔在数字化器表面移动时,将发生 数据包 通知。 发生这种情况时,应用程序会将新的 StylusDownData 添加到 Stylus 对象的数据包数组中。 它通过使用 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

访问和操作触笔输入