在您的 .NET 应用程序中处理触摸、笔或鼠标数字化仪输入






4.81/5 (9投票s)
一个简单的应用程序,展示了您如何确定用户输入来自鼠标、平板电脑数字化仪还是触摸。

引言
使用 Windows Vista 中内置的平板电脑技术,您可以使您的应用程序能够对不同的输入设备(如笔、鼠标和触摸输入)执行独特的操作 - 即使在台式电脑上也是如此。
背景
借助 Windows Vista,平板电脑 PC 的软件功能已内置到核心操作系统中。这意味着您可以在 Vista 应用程序中添加对墨迹、手写识别的支持,而无需担心重新分发 DLL 或担心用户是否使用的是平板电脑 PC。在 Windows XP 中,您必须拥有一台平板电脑 PC 才能通过操作系统中的 API 将笔用作输入设备。
我可以用这种功能做什么?
数字化仪已被图形艺术家使用了多年,并且平板电脑 PC 硬件将这种输入直接集成到了显示器中。现在,触摸(电阻式和电容式)数字化仪以及电磁数字化仪也出现在移动 PC 和台式 LCD 显示器上。有些 PC 甚至集成了双模式数字化仪,这样您就可以在笔处于范围内时在屏幕上书写,然后当您用手指触摸屏幕时,它会自动切换到触摸模式。我认为这是一个为应用程序添加新功能的绝佳机会。
设想一个场景:您有一个照片应用程序,允许您直接在照片上用笔写下关键字(这本身就很酷),然后当您伸出手用手指触摸显示屏时,应用程序会切换到平移模式,以便您可以移动照片。非常酷。
使用代码
我使用了 Windows SDK 中现有的 RealTimeStylus 示例应用程序作为此示例的基础。RealTimeStylus
对象 (RTS) 允许您从连接的数字化仪或鼠标设备收集数据,并使您能够即时处理这些数据。您可以在 RealTimeStylus 中添加、删除和重新排序不同的插件,这意味着您可以动态地更改输入呈现方式。
由于示例应用程序具有我需要的大部分功能,因此我想添加根据当前用户输入来源确定输入设备的功能。RealTimeStylus 是平板电脑 PC 功能的一部分,这意味着它会用到墨迹,但情况并非总是如此。我只是可以将 RTS 的输入用于任何我想要的东西。
让我们开始确保我们通过订阅 DataInterestMask
来接收正确的事件。我想确保我们能收到输入开始、应用程序接收数据以及可能发生的任何错误的通知。
public DataInterestMask DataInterest
{
get
{
return DataInterestMask.StylusDown | DataInterestMask.Packets |
DataInterestMask.Error;
}
}
接下来,我需要确保我为上述通知添加了处理程序。确定输入来源以及如何处理它的步骤很简单:
- 在
StylusDown
事件中,查询输入的来源设备类型。 - 在 Packets 事件中,选择处理传入的数据。在我的例子中,我将根据数据包来自的输入设备绘制不同颜色的椭圆。
StylusDown
事件与 MouseDown 事件非常相似——它会通知您即将发生输入。这给了我们机会查询用户正在与之交互的输入设备。这里的 Tablet
对象描述了当前输入设备的所有功能,包括类型或 DeviceKind
枚举。
public void StylusDown(RealTimeStylus sender, StylusDownData data)
{
Tablet currentTablet =
sender.GetTabletFromTabletContextId(data.Stylus.TabletContextId);
if(currentTablet != null)
{
// Keep track of the current input device type
tabletKind = currentTablet.DeviceKind;
}
}
现在您知道哪个输入设备将要创建数据,就需要添加一个 Packets
事件的处理程序。这会根据我们在上一个处理程序中跟踪的当前 TabletDeviceKind
进行切换,并为每种设备类型执行不同的操作。我只是为每种输入设备绘制不同颜色的椭圆。
public void Packets(RealTimeStylus sender, PacketsData data)
{
// For each new packet received, extract the x,y data
// and draw a small circle around the result.
for (int i = 0; i < data.Count; i += data.PacketPropertyCount)
{
// Packet data always has x followed by y followed by the rest
Point point = new Point(data[i], data[i+1]);
// Since the packet data is in Ink Space coordinates, convert to
// Pixels
point.X = (int)Math.Round((float)point.X *
(float)myGraphics.DpiX/2540.0F);
point.Y = (int)Math.Round((float)point.Y *
(float)myGraphics.DpiY/2540.0F);
// Draw a circle corresponding to the packet
switch (this.tabletKind)
{
case TabletDeviceKind.Pen:
// Make the packets from the stylus smaller and green
myGraphics.DrawEllipse(Pens.Green, point.X - 2, point.Y - 2,
4, 4);
break;
case TabletDeviceKind.Mouse:
// Make the packets from the mouse/pointing device mid-sized
// and red
myGraphics.DrawEllipse(Pens.Red, point.X - 2, point.Y - 2,
10, 10);
break;
case TabletDeviceKind.Touch:
// Make the packets from a finger/touch digitizer larger and
// blue
myGraphics.DrawEllipse(Pens.Blue, point.X - 2, point.Y - 2,
20, 20);
break;
}
}
}
关注点
上面的示例仅检查来自鼠标、触摸或笔设备的数据包的 X 和 Y 坐标。但是,数字化仪还可以有其他数据包类型。电磁数字化仪(无论是内置在平板电脑 PC 中还是 USB 外置数字化仪)还可以提供压力数据。添加此支持将允许此示例应用程序根据用户在数字化仪上的按压力度来改变绘制的每个椭圆的大小。也许这将是对本文的更新。
这些 API 是 Windows Vista 的新功能,在 .NET 2.0、C++ COM 以及 .NET 3.0 的 Windows Presentation Foundation (WPF) 中可用。
历史
2007 年 3 月 6 日 - 创建文章