本申请声明了对2003年10月24日提交的标题为《写字板平台控件和API》的美国申请(序号为60/513,591)的优先权,该美国申请的内容被特别包括于此,用作参考。
具体实施方式
本发明的各个方面涉及:按有效率的方式来处理针笔事件,以便向用户迅速地呈现电子墨水。
本文档被分成各个章节,以帮助读者。这些章节包括:墨水的特征、术语、通用计算环境、实时墨迹作图纵览、对象模型、动态呈现和湿墨水、手势识别、同步和异步过程、级串联、动态插入程序集合修改、错误传播、被管理/未被管理的举例说明、数据集和数据流、数据同步、以及应用编程接口。
墨水的特征
如使用墨水笔的用户所知道的,与线段所连接的一系列坐标相比,物理墨水(使用具有墨水储存器的笔而被置于纸上的那种类型的墨水)可以传达更多信息。例如,物理墨水可以反映笔压力(通过该墨水的浓度)、笔角度(通过这些直线或曲线段的形状以及离散点周围的该墨水的行为)、该笔尖的速度(通过直线性、行宽度、以及直线或曲线的路线上的行宽度变化)。进一步的例子包括墨水被吸入它沉淀于其上的纸纤维或其他表面的方法。这些微妙的特征也有助于传达以上列出的各个属性。由于这些附加的属性,与利用各个点之间的均匀的线宽度相比,可以更在瞬间传达情绪、个性、强调等。
电子墨水(或墨水)涉及当用户使用基于针笔的输入设备时被捕捉的电子信息的捕捉和显示。电子墨水指的是笔划的序列或任何任意的集合——在那里,每个笔划由一连串点组成。这些笔划可以被同时绘制或集合,也可以在独立的时间和位置、出于独立的原因而被绘制或集合。可以使用各种已知技术(包括笛卡儿坐标(X,Y)、极坐标(r,Θ)和如本技术领域中已知的其他技术)来表示这些点。电子墨水可以包括真墨水的属性的表示(包括压力、角度、速度、颜色、针笔尺寸和墨水不透明度)。电子墨水可以进一步包括其他属性——包括(在其他信息之中)墨水如何沉淀于纸上的顺序(关于大多数西方语言,是左至右然后向下的进行模式)、时标(指出何时沉淀该墨水)、该墨水的作者的指示、以及发起设备(在其上绘制该墨水的机器的识别或被用来沉淀该墨水的该笔的识别中的至少一项)。
术语
墨水 具有属性的笔划序列或笔划集。笔划序列可以包括以有序形式的笔划。可以通过被捕捉的时间、或通过这些笔划出现在纸上的地方、或通过该墨水的作者在协作的情况中来对该序列进行排序。可能存在其他顺序。笔划集可以包括笔划序列、或无序的笔划、或其任何组合。另外,一些属性对于每个笔划或该笔划中的点而言可以是独特的(例如,压力、速度、角度等)。这些属性可以被存储在该笔划或点层次处,而不是在该墨水层次处。
墨水对象 具有或没有属性的、存储墨水的数据结构。
笔划 被捕捉的点序列或点集。例如,当被呈现时,该点序列可以
与直线连接。另外,该笔划可以被代表为一个点和在下一个
点的方向上的向量。简而言之,笔划意在包含涉及墨水的点
或段的任何表示,而不管点和/或什么连接这些的点基础表
示。
点 定义空间中的位置的信息。例如,可以相对于捕捉空间(例如,
数字转换器上的点)、虚拟墨水空间(被捕捉的墨水被放入其
中的空间中的坐标)和/或显示空间(显示设备的这些点或像
素)来定义这些点。
文档 具有可视表示和内容的任何电子文件。文档可以包括网页、
文字处理文档、记事页或记事本、电子表格、可见展示、数
据库记录、图像文件及其组合。
实时针笔 该实时针笔尖是在给定窗口输入矩形内的给定窗口处理上
提供实时针笔事件的对象。该实时针笔也可以被认为是构
架,可为该构架加入处理附加功能的插入程序对象。这些插
入程序对象可以在这些实时针笔该所需功能性改变时加入
和除去。关于该实时针笔的该API可以被称作“RTS”。RTS
可以是核心API部件,开发者可以将其他功能系于该核心
API部件。该RTS包装来自笔服务的该原始数据,并将该数
据转发到该第一个插入程序对象(如果有的话)。该实时针笔
可以具有一个或多个接口。在两个接口的情况中,这些可以
是同步接口和异步接口。这些接口提供插件程序可以被连接
到该实时针笔的位置。这些接口只用于说明的目的。也可以
使用其他接口。
实时墨水 实时墨水是“墨水正从该针笔的尖端流出”的虚幻的样子。
原先的方法已尝试将重要的处理步骤与该墨水呈现耦合起
来,从而减缓新近接收的笔划的显示。实时墨水尝试在接收
这些新近接收的笔划时推动它们显示,并且尝试分开这些实
时处理步骤和该实时显示来一起操作,从而更快地向用户显
示墨水。
插件程序 插件程序是可以被加入该实时针笔对象的功能组件。如果插
件程序被附加到该实时针笔对象的同步接口,那么,它可以
被称作“同步插件程序”。如果插件程序被附加到该实时针
笔对象的异步接口,那么,它可以被称作“异步插件程序”。
笔服务 系统服务部件,它与该数字转换器硬件驱动器连接,并提供
已被预先解释为标准“数据包”和相关结构的原始“数据包”
数据、以及仍然与“写字板”功能性(例如,
TabletAdded/Removed、StylusButtonUp/Down等)有关的独立
于墨水集合的其他通知。笔服务提供用于通过插入程序集合
来处理数据包的主要机制。
插入程序集合 一个或多个组中的插件程序的集合,它们被附加到该
RTS。在存在两个集合的情况下,它们可以分别与该RTS的
同步接口和异步接口相关联。可以有秩序地执行每个集合。
在存在两个或更多的集合的情况下,它们可以彼此独立地来
加以执行,因为它们可以附加到该RTS(或多个RTS)的不同
的接口。在被每个插件程序处理之后,数据返回到该RTS。
该集合中的插件程序的顺序可以影响该集合的输出。
插入式链 插件程序链——在那里,插件程序的每个编组被串联连接。
这里,在返回到该RTS之前,通过该链中的每个插件程序数
据按自己方式工作。该链也可以被称作“插件程序的‘菊花
链’”。该链或菊花链中的这些插件程序的该顺序可以影响
该链的输出。
输入队列 对于被同步插入程序集合或插入式链生成的数据包或对象
的临时保持队列,用于由该同步插入程序集合或插入式链来
进行再处理。简而言之,该同步插入程序集合或插入式链可
以将对象推入输入队列。
动态呈现 在该笔正接触该屏幕的同时,绘制墨水的该递增过程。当该
笔跨越该数字转换器而移动时,在该屏幕上留下“墨水”的
痕迹。该效果看起来好象是在绘制时墨水正从该笔流出。当
接收该数据时,逐点地绘制该墨水。该呈现也可以让附加的
效果被应用(例如,防混淆等)。
静态呈现 同时呈现整个墨水笔划的该过程。在绘制该墨水并且这整个
笔划被绘制为单一单位之前,该数据已可用。静态呈现也可
以让附加的效果被应用(例如,贝塞尔平滑法和防混淆)。
动态呈现器 该开发者可以随意地例示动态呈现器,以便自动为GDI呈现
表面提供实时数据包数据的非常有效率的呈现。对于其他呈
现表面的动态呈现器(比如DirectX或绘图仪),可能使用用
作为本发明的各个方面的实施的一部分来提供的GDI-中心
DynamicRenderer相同的接口定义。
手势识别器 开发者能可选地例示手势识别器,以便执行笔划的实时识
别,并报告一个或多个笔划何时组成该开发者已表示感兴趣
的手势。该手势识别器可以(如果它被使用的话)被放入该同
步或异步集合或链。
输出队列 一旦该数据包数据已流过该对象集合或链(并且潜在地已被
修改),它就被沉淀在该输出队列中——在那里,该RTS将
它发送到异步插件程序集合或链。
InkCollectingObject 描述累积并存储由“实时针笔”所提供的墨水数据的
异步插入程序对象。
ICO 可能在异步集合或链中的墨水集合对象。它从该输出队列那
里接收数据。
通用计算环境
图1A展示了可以在其上执行本发明的合适的计算系统环境100的例子。该计算系统环境100只是合适的计算环境的一个例子,它并不意在对本发明的使用或功能性的范围提出任何限制。也不应该将计算系统环境100解释为具有对示范计算系统环境100中所展示的任何一个部件或部件组合有任何依赖或要求。
本发明可用于众多其他的通用或专用计算系统环境或配置。可能适用于本发明的众所周知的计算系统、环境和/或配置的例子包括(但不局限于)个人计算机、服务器计算机、包括智能电话、智能手表和个人数据助理的手持设备或便携式设备、多处理器系统、基于微处理器的系统、机顶盒、可编程的消费电子设备、网络PC、小型计算机、大型计算机、包括以上任何系统或设备的分布式计算环境等。
可以在由计算机执行的计算机可执行指令(例如,程序模块)的一般上下文中描述本发明。通常,程序模块包括执行特定任务或实施特定的抽象数据类型的例行程序、程序、对象、组件、数据结构等。也可以在分布式计算环境中实践本发明,在这些分布式计算环境中,由通过通信网络而被连接的远程处理设备来执行任务。在分布式计算环境中,程序模块可以位于包括记忆存储设备的本地和远程计算机存储介质中。
参照图1A,用于执行本发明的示范系统包括采取计算机110的形式的通用计算设备。计算机110的部件可以包括(但不局限于)处理单元120、系统存储器130和系统总线121,该系统总线121将包括系统存储器的各种系统部件耦合到处理单元120。系统总线121可以是几种类型的总线结构(包括存储总线或存储控制器、外围总线和使用各种总线构造中的任一种的局域总线)中的任一种。举例来讲(不作限制),这类结构包括“工业标准体导结构”(ISA)总线、“微通道结构”(MCA)总线、“增强型ISA”(EISA)总线、“视频电子技术标准协会”(VESA)局域总线和“外围部件互连”(PCI)总线(也被称作Mezzanine总线)。
计算机110通常包括各种计算机可读介质。计算机可读介质可以是可由计算机110存取的任何可用介质,它包括易失和非易失介质、可移动和不可移动的介质。举例来讲(不作限制),计算机可读介质可以包括计算机存储介质和通信介质。计算机存储介质包括易失和非易失的可移动和不可移动的介质,该介质用对于信息(例如,计算机可读指令、数据结构、程序模块或其他数据)存储的任何方法或技术来加以实现。计算机存储介质包括(但不局限于)随机存取存储器(RAM)、只读存储器(ROM)、电可擦除可编程只读存储器(EEPROM)、闪存或其他存储技术、CD-ROM、数字通用光盘(DVD)或其他光盘存储器、盒式磁带、磁带、磁盘存储器或其他磁性存储设备、或可以被用来存储所需信息并可以由计算机110来进行存取的其他任何介质。通信介质通常具体表现为在调制数据信号(例如,载波或其他传送机制)中的计算机可读指令、数据结构、程序模块或其他数据,并包括任何信息传递介质。该术语“调制数据信号”意味着一种信号,其一个或多个特征组按为该信号中的信息编码的这样一种方式来加以设置或更改。举例来讲(不作限制),通信介质包括有线介质(例如,有线网络或直线连接)和无线介质(例如,声音、RF、红外线和其他无线介质)。以上任何内容的组合也应该被包括在计算机可读介质的范围以内。
系统存储器130包括采取易失和/或非易失存储器的形式的计算机存储介质(例如,ROM 131和RAM 132)。基本输入/输出系统133(BIOS)通常被存储在ROM 131中,该基本输入/输出系统包含有助于在计算机110内的各个元件之间传送信息(例如,在启动期间)的这些基本例行程序。RAM 132通常包含可立即由处理单元120存取和/或目前正由处理单元120进行操作的数据和/或程序模块。举例来讲(不作限制),图1A展示了操作系统134、应用程序135、其他程序模块136和程序数据137。
计算机110也可以包括其他可移动/不可移动,易失/非易失计算机存储介质。只举例来讲,图1A展示了从不可移动的非易失磁性介质读取或对其写入的硬盘驱动器141、从可移动的非易失磁盘152读取或对其写入的磁盘驱动器151,以及从可移动的非易失光盘156(例如,CD ROM或其他光学介质)读取或对其写入的光盘驱动器155。可以被用于该示范操作环境中的其他可移动/不可移动的易失/非易失计算机存储介质包括(但不局限于)卡型盒式磁带机、闪存卡、数字通用光盘、数字视频带、固态RAM、固态ROM等。硬盘驱动器141通常通过不可移动的存储接口(例如,接口140)而被连接到系统总线121,磁盘驱动器151和光盘驱动器155通常由可移动的存储接口(例如,接口150)连接到系统总线121。
以上所讨论的和图1A中所展示的这些驱动器及其关联的计算机存储介质为计算机110提供计算机可读指令、数据结构、程序模块和其他数据的存储。在图1A中,例如,硬盘驱动器141被展示为存储操作系统144、应用程序145、其他程序模块146和程序数据147。注意,这些组件可以等同于或不同于操作系统134、应用程序135、其他程序模块136和程序数据137。这里为操作系统144、应用程序145、其他程序模块146和程序数据147提供不同的序号,以展示:它们至少是不同的副本。用户可以通过输入设备(例如,数码照相机163、键盘162和通常被称作“鼠标”、“跟踪球”或“触垫”的定位设备161),来将命令和信息输入计算机110。其他输入设备(未示出)可以包括话筒、操纵杆、游戏垫、圆盘式卫星电视天线、扫描仪或类似的输入设备。这些和其他的输入设备经常通过被耦合到系统总线121的用户输入接口160而被连接到处理单元120,但也可以由其他接口和总线结构(例如,并行端口、游戏端口或通用串行总线(USB))来加以连接。监视器191或其他类型的显示设备也经由接口(例如,视频接口190)而被连接到系统总线121。除该监视器以外,计算机也可以包括其他外围输出设备(例如,扬声器197和打印机196),这些外围输出设备可以通过输出外围接口195来加以连接。
计算机110可以使用与一台或多台远程计算机(例如,远程计算机180)的逻辑连接而在联网环境中进行操作。远程计算机180可以是个人计算机、服务器、路由器、网络PC、对等设备或其他公共网络节点,它通常包括以上相对于计算机110而描述的许多或所有这些元件,尽管图1A中只展示了记忆存储设备181。图1A中所描绘的这些逻辑连接包括局域网(LAN)171和广域网(WAN)173,但也可以包括其他网络。这类联网环境在办公室、企业范围的计算机网络、内联网和因特网中很普遍。
当被用于LAN联网环境中时,计算机110通过网络接口或适配器170而被连接到LAN 171。当被用于WAN联网环境中时,计算机110通常包括调制解调器172或用于在WAN 173(例如,因特网)上建立通信的其他装置。调制解调器172(可能是内置的,也可能是外置的)可以经由用户输入接口160或其他适当的机制而被连接到系统总线121。在联网环境中,相对于计算机110描绘的程序模块或其各个部分可以被存储在远程记忆存储设备中。举例来讲(不作限制),图1A将远程应用程序185展示为驻留在存储设备181上。应理解:所示的这些网络连接起示范的作用,可以使用在这些计算机之间建立通信链路的其他手段。
应理解:所示的这些网络连接起示范的作用,并且,可以使用在这些计算机之间建立通信链路的其他手段。假定存在各种众所周知的协议(例如,TCP/IP、以太网、FTP、HTTP等)中的任何协议,并且,该系统可以在客户机-服务器配置中操作,以许可用户从基于web的服务器中检索网页。可以使用各种常规web浏览器中的任何web浏览器来在网页上显示并处理数据。
编程接口(或更简单地被称作“接口”)可以被视作用于允许一个或多个代码段与一个或多个其他的代码段所提供的功能进行通信或访问该功能的任何机制、过程、协议。另外,编程接口可以被视作能够按通讯联络的方式耦合到其他组件的一个或多个机制、方法、功能调用、模块等的、系统的部件的一个或多个机制、方法、功能调用、模块、对象等。前一个句子中的该术语“代码段”意在包括一个或多个指令或代码行,并且包括(例如)代码模块、对象、子程序、函数等,而不管:所应用的术语或这些代码段是否被个别地加以编译,或这些代码段是否作为源代码、中间代码或目标代码来加以提供,这些代码段是否被用于运行时间系统或过程中,或它们是位于相同的或不同的机器上、还是跨越多个机器来加以分布,或是否完全在软件中、完全在硬件中、还是在硬件和软件的组合中执行这些代码段所表示的功能。
在概念上,如图1B或图1C所示,可以一般地观察编程接口。图1B展示了作为管道的接口Interface1,第一和第二代码段通过该管道来进行通信。图1C将接口展示为包括接口对象I1和I2(它们可能是或可能不是该第一和第二代码段的一部分),它们允许系统的第一和第二代码段经由介质M来进行通信。在图1C的该视图中,可以认为接口对象I1和I2是同一系统的分开的接口,也可以认为:对象I1和I2加上介质M包括该接口。虽然图1B和1C示出了双向流和该程的每侧上的接口,但是,某些实施可以只在一个方向上具有信息流(或如下所述,无信息流),或者只可以在一侧上具有接口对象。举例来讲(不作限制),诸如应用编程接口(API)、入口点、方法、函数、子程序、远程过程调用和部件对象模型(COM)等术语被包含在编程接口定义内。
这种编程接口的各个方面可以包括:第一代码段将信息(那里的“信息”有最广义的运用,并包括数据、命令、请求等)传送到第二代码段的方法;第二代码段由此来接收该信息的方法;以及该信息的结构、序列、句法、组织、模式、定时和内容。在这方面,只要按该接口所定义的方式来传送该信息,对于该接口的该操作、该介质是有线的还是无线的或是两者的组合而言,该基础传输介质本身就可能是不重要的。在某些情况中,从常规意义上说,可能不在一个或两个方向上传递信息,因为该信息传输可以要么经由另一个机制(例如,信息被放入缓冲器、文件等中,与这些代码段之间的信息流分开),要么不存在,如同当一个代码段仅仅访问第二代码段所执行的功能性时那样。任何或所有这些方面在给定的情况中可能都很重要——例如,取决于这些代码段是否是松散耦合的系统或紧密耦合的配置中的一部分;所以,这个清单应该被认为是起说明性作用,而非限制性作用。
编程接口的这个概念是精通该技术领域的人已知的,并且从本发明的前述详细说明中可清楚、易懂。但是,有其他方法来执行编程接口,并且,除非被明确地排除在外,这些方法也意在被本说明书末尾所陈述的权利要求书包含在内。这类其他的方法可能看起来比图1B和1C的该简单化视图更加高级或复杂,但它们却执行类似的功能,以实现相同的总体结果。现在,将简要地描述编程接口的一些说明性的选择性实施。
A.分解
通过将从一个代码段到另一个代码段的通信分成多个离散通信,可以间接地实现该通信。这一点在图1D和1E中被示意地加以描绘。如所示,可以按照可分的功能组来描述一些接口。这样,图1B和1C中的该接口功能可以被分解,以得到相同的结果,就如同可以在数学上提供24或2乘以2乘以3乘以2。相应地,如图1D所示,接口Interface1所提供的该功能可以被再分,以便将该接口的各个通信转换成多个接口Interface1A、Interface1B、Interface1C等,同时,得到相同的结果。如图1E所示,接口I1所提供的功能可以被再分成多个接口I1a、I1b、I1c等,同时,得到相同的结果。同样,从第一代码段接收信息的第二代码段的接口I2可以被分解成多个接口I2a、I2b、I2c等。当进行分解时,被包括于第1代码段的接口数量不需要与被包括于第2代码段的接口数量相匹配。在图1D和1E的任何一种情况中,接口Interface1和I1的功能本质上分别保持与图1B和1C相同。接口的分解也可以遵循联合属性、可交换属性和其他的数学属性,以便该分解可能会难以识别。例如,操作的排序可能是不重要的,所以,由一个接口所执行的功能可以在达到该接口之前被另一个代码或接口很好地执行,或者可以由该系统的单独部件来执行。而且,掌握这些编程艺术领域的普通技能的人会理解:有各种方法来执行可得到相同结果的不同的功能调用。
B.重新定义
在一些情况中,可以忽视、增加或重新定义编程接口的某些方面(例如,参数),同时,仍然实现预定的结果。图1F和1G展示了这一点。例如,假设:图1B中的接口Interface1包括功能调用“平方”(输入,精度,输出)——包括输入、精度和输出这三个参数的调用,它从第1“代码段”被发出到第2“代码段”。如果如图1F所示,该中间参数精度在给定的情形中无关紧要,那么,它可以同样被忽视或甚至被无意义的(在此情况中)参数取代。也可以增加无关紧要的附加的参数。无论哪种情况,只要由第二代码段来平方输入之后返回输出,就可以实现该平方功能性。对于该计算系统的某个下游或其他部分而言,精度很可能是有意义的参数;但是,一旦认识到“精度对于‘计算该平方’的狭窄目的而言是不必要的”,它就可以被取代或被忽视。例如,可以在“不对该结果造成不利影响”的条件下传递无意义的值(例如,出生日期),而不是传递有效精度值。同样,如图1G所示,接口I1被接口I1’取代,并被重新定义成忽视参数或将它们加入该接口。接口I2同样可以被重新定义为接口I2’,并被重新定义成忽视不必要的参数、或可以在别处加以处理的参数。这里的要点是:在一些情况中,编程接口可以包括因某个目的而不需要的方面(例如,参数),所以,它们可以被忽视或被重新定义,或为其他目的而在别处加以处理。
C.联机编码
也可以合并两个单独的代码模块的部分或全部的功能,使湿它们之间的“接口”更改形式。例如,图1B和1C中的功能性可以被分别转换成图1H和1I中的功能性。在图1H中,图1B中的先前的第1和第2“代码段”被合并成包含它们两者的模块。在此情况下,这些代码段可能仍然彼此进行通信,但该接口可能适应更适合该单一模块的形式。这样,例如,正式的“调用”和“返回”语句可能不再是必要的,但遵循接口Interface1的类似的处理或响应可能仍然有效。同样,如图1I所示,来自图1C的接口I2的一部分(或全部)可以被联机写入接口I1,以构成接口I1”。如所展示的,接口I2被分成I2a和I2b,并且,已利用接口I1来对接口部分I2a进行联机编码,以构成接口I1”。具体举例来讲,考虑到:来自图1C的接口I1执行功能调用square(输入,输出),它被接口I2接收,并且,在处理第二代码段所传递的、具有输入的值(以计算输入的平方)之后,它传回具有输出的该平方结果。在这种情况下,第二代码段(平方输入)所执行的处理可以由第一代码段来执行,而无须调用接口。
D.分离
通过将从一个代码段到另一个代码段的通信分成多个离散通信,可以间接地实现该通信。这一点在图1J和1K中被示意地加以描绘。如图1J所示,提供一个或多个代码(“脱离接口”,因为它们从原始接口分离功能和/或接口功能),以转换第一接口——Interface1上的这些通信,从而使它们符合不同的接口(在此情况下是接口Interface2A、Interface2B和Interface2C)。可以执行这一点——例如,其中,有被安装的应用程序库,它被设计成(比方说)根据Interface1协议与操作系统进行通信,但是另一方面,该操作系统被更改成使用不同的接口(在此情况下是接口Interface2A、Interface2B和Interface2C)。该要点是:更改第2“代码段”所使用的原始接口,以便它不再与第1“代码段”所使用的接口相兼容,所以,使用中介物来使该新、旧接口兼容。同样,如图1K所示,可以利用分离接口DI1来引入第三代码段,以便从接口I1那里并利用分离接口DI2来接收这些来自接口I1的通信,并用分离接口DI1将接口功能性传送到(例如)接口I2a和I2b,这些接口被重新设计成与DI2一起运作,但提供相同的功能结果。同样,DI1和DI2可以一起运作,以便将图1C中的接口I1和I2的该功能性转化为新的操作系统,同时,提供相同的或类似的功能结果。
E.重写
另一个可能的变体是:动态地重写该代码,以便用可实现相同的总体结果的其他某物来取代该接口功能性。例如,可能有一种系统——其中,用中间语言来呈现的代码段(例如,微软IL、Java ByteCode等)被提供给在执行环境(例如,.Net构架所提供的环境、Java实时运行环境、或其他类似的实时运行类型环境)中的Just-in-Time(JIT)编译器或解释器。该JIT编译器可以被写入,以便动态地转换从第1“代码段”到第2“代码段”的这些通信,即,使它们符合如第2“代码段”(原始的或不同的第2“代码段”)可能要求的不同的接口。图1L和1M描绘了这一点。如在图1L中可见,这个方法类似于以上所描述的“分离”情形。它可以被执行——例如,其中,被安装的应用程序库被设计成与根据Interface1协议的操作系统进行通信,但是然后,该操作系统被更改成使用不同的接口。该JIT编译器可以被用来使来自这些被安装库应用程序的运行的这些通信符合该操作系统的这个新接口。如图1M中所描绘的,这个“动态地重写这个(这些)接口”的途径可以被应用于动态地对这个(这些)接口进行分解,或者还改变它们。
也要注意,用于经由另实施例来实现与接口相同的或类似的结果的上述情形也可以用各种方法、连续地和/或并行地、或与其他介入代码相结合。这样,以上所给出的这些另选实施例不是相互排斥的,它们可以混合、匹配和组合起来,以产生与图1B和1C中所呈现一般情形等同于或相当的情形。也要注意,关于大多数编程构造,有“实现这里可能没有描述但由本发明的精神的范围表示的接口的相同的或类似的功能性”的其他类似的方法,即,注意,它至少部分是由成为接口的价值的基础的接口来表示的该功能、并由该接口来启用的这些有利的结果。
图2展示了可以根据本发明的各个方面来加以使用的说明性写字板PC201。图1的该系统中的任何或所有这些特点、子系统和功能都可以被包括在图2的该计算机中。写字板PC 201包括其上显示多个窗口203的大型显示表面202(例如,数字化平板显示器、较佳的是液晶显示器(LCD)屏幕)。通过使用针笔204,用户可以在该数字化显示表面202上选择加亮和/或书写。合适的数字化显示表面202的例子包括电磁笔数字转换器(例如,Mutoh或Wacom笔数字转换器)。也可以使用其他类型的笔数字转换器(例如,光学数字转换器)。写字板PC 201解释使用针笔204而作出的手势,以便处理数据,输入文本,创建绘图,和/或执行常规计算机应用任务(例如,电子表格、文字处理程序等)。
针笔204可以装备有一个或多个按钮或其他特点,以增大其选择能力。在一个实施例中,该针笔204可以作为“铅笔”或“钢笔”来加以执行——其中,一端组成书写部分,另一端组成“擦除器”端,并且,当跨越该显示器而移动时,它指出:该显示的各个部分将要被擦除。可以使用其他类型的输入设备(例如,鼠标、跟踪球、或类似物)。此外,用户自己的手指可以是针笔204,并且可以被用于在触敏式或接近-敏感式显示器上选择或指出该被显示的图像的各个部分。所以,如这里所使用的,该术语“用户输入设备”意在具有广泛的定义,并包含众所周知的输入设备上的许多变种(例如,针笔204)。区域205示出反馈区或接触区,从而允许用户确定针笔204接触显示表面202的地方。
在各个实施例中,该系统提供墨水平台,如应用程序可以用来捕捉、操作和存储墨水的一套COM(部件对象模型)服务。一项服务允许应用程序使用所揭示的墨水为代表来读、写墨水。该墨水平台也可以包括标记语言——包括象可扩展标记语言(XML)的语言。另外,该系统可以将DCOM用作另一项实施。可以使用更多的实施——包括来自微软公司的Win32编程模型和.Net编程模型。
实时墨迹作图纵览
用户使用针笔或笔,创建电子墨水。该墨水由系统来处理,该系统允许更接近于该用户创建该墨水的时间来显示该墨水,而不是一直等到附加的过程已完成。
图3示出了根据本发明的各个方面的用于处理电子墨水的说明性系统。输入管理器在输入管理器301中接收墨水。该技术领域中存在各种输入管理器——包括笔和数字化写字板、Wacom写字板等。该墨水数据的存在指的是“针笔输入事件302”。接下来,该针笔输入事件302由墨水集合器303来处理。该墨水集合对象303执行来自该输入管理器301的信息的最初处理。然后,该系统动态地呈现墨水304,供在显示器305上输出。其他部件可以处理更完整的墨水处理。例如,笔划可以被加入现存的墨水对象306(或者可以创建新的墨水对象,以包含该墨水笔划),并可以将该被接收的墨水(被称作“数据”)与一个或多个属性联系起来。这一点由具有墨水对象属性307的部件来示出。然后,可以重画308该墨水对象(如果需要光滑的话),供在显示器305上显示。
图4示出了对于图3中的方法的替换方法。图4包括内部针笔输入源401、输入管理器402(可能具有或可能不具有输入队列)、墨水集合对象403、具有墨水对象属性的元件405、实时墨迹作图对象404和显示器406。
可以处理两种类型的输入集:从针笔与数字转换器之间的接触产生的数据、以及从在数字转换器之上进行的运动产生的数据。不接触该数字转换器的、在该数字转换器之上进行的这些运动被称作“‘空中针笔’输入”。该内部针笔输入源分开这两个输入集,并相应地发送它们。以下列出发生在图4中的各种动作:
A)空中针笔输入事件被加入输入管理器402的输入队列。
B)该输入管理器402将空中针笔输入派遣给墨水集合403。
C)该输入管理器402也输出用于处理的该空中针笔输入,以确定:是否已发生焦点变化。也通知实时墨迹作图对象404(也被称作“实时针笔控制器”)。该实时墨迹作图对象404可以请求任何需要的数据(墨水颜色等)。
D)该空中针笔事件继续正常处理,并继续进行到具有墨水对象属性的元件405。
E)针笔“向下”事件被接收,并被发送到该实时墨迹作图对象405。
F)当接收点时,实时墨迹作图对象405绘制这些点。这可以被称作“动态呈现”。
G)实时墨迹作图对象405将这些被绘制的事件转发到输入管理器402,以便在当用户接口线程成为可用时的以后某个时间加以派遣。
H)笔划被集合,然后被加入到墨水对象。
I)该元件首先通知该实时墨迹作图对象405除去这个被动态绘制的笔划,然后重画那个新笔划。这个操作可以在逐个笔划的基础上发生,或者可以应用于墨水笔划上。
J)在所有墨迹作图完成之后,呈现该墨水。
如图4所示的以上方法提供了一些好处:墨水滞后只对于“针笔向下”事件而言是紧要的。在该针笔正积极绘制的同时,墨水滞后只是可察觉的。可以延迟所有其他的针笔事件,而只有很少消极的用户影响。
图4中的方法提供正被定位在该输入管理器队列和该RTI对象中的多线程意识。也保证:一旦已建立焦点,将无滞后或延迟。
对象模型
图5示出了可以结合本发明来加以使用的各种对象——包括可以在各种程度上被结合起来的五个部分。以下列出下文中所使用的各种术语:
第一个部分是支持电子墨水搜集的笔服务应用程序501。例子是从微软公司提供的并且被用于Windows XP写字板编输中的wisptis.exe。
其次,实时针笔服务503(与过程1 502联合示出)是将针笔数据从笔服务501那里转发到这些适当的用于集合的窗口的应用程序。该实时针笔服务503可以处理无限数量的对象,或者可以被限制为在使用上进行最小化。例如,如果有限的话,每一线程的对象的说明性数量可能是16、32、64、128等。当然,可以使用其他值。
第三,在过程1中示出实时针笔504和505。实时针笔504和505可以从实时针笔服务503那里接收针笔数据。每个实时针笔对象可能正在接收关于窗口或区域的给定部分的针笔数据(基于关于那个实时针笔对象的关联的窗口或区域)。
为了示出如何可以同时执行多个过程,也示出过程2 506。实时针笔服务507也可以从笔服务501那里接收针笔数据,并将该信息转发到实时针笔508和509。
在图6中,更详细地示出实时针笔对象504、505、508和509。笔服务部件601在数据流A中将数据转发到实时针笔服务602。接下来,实时针笔服务602在数据流B中将针笔数据转发到一个或多个实时针笔部件603上。另外,如虚线所表现的实时针笔服务602所示,可以省略这项服务,并且,针笔数据直接流到实时针笔部件603。
在实时针笔部件603处被接收的该针笔数据可以被直接馈送到可插部件606-608。另外,所接收的针笔数据可以被馈入其输入队列604,用于有序处理。实时针笔部件603接下来将针笔数据转发一个或多个可插部件。这些部件606-608可以包括动态呈现器608——具有存储当前被呈现的针笔数据的可见存储器。这些数据流包括流C和D。
动态呈现器608可以将关于一个或多个笔划的数据包数据累积和存储在可见存储器609中。例如,如果笔划扩展到边缘以外,然后再进入可用墨水区域,同时,该针笔仍然向下,那么,这是有利的。如果该显示窗口接收重画请求,同时,该笔向下,那么,该存储器609提供该信息,以迅速重画该窗口。如果该动态呈现器没有将针笔数据存储在609中,那么,该系统将必须等候重画该窗口并呈现这个或这些最当前的笔划,直到该数据使它从该输出队列中出来并进入墨水集合对象611。
可插部件606-608是类别对象,这些类别对象可以通过接口来响应于某些调用,以处理针笔数据。可以被使用的接口的一个例子包括IstylusSyncPlugin。可插部件606-608的组合允许开发者充分地控制、修改、甚至从这些插件程序内的该数据包流中删除数据。然后,来自数据流E的该被修改的数据包流被存储在输出队列605中。
输出队列605的输出通过数据流F和G而流动到可插部件610和611的另一个集合。这些部件可以包括手势识别器610和具有墨水存储器612的墨水集合对象611。可以由数据流F和G来打开发各种附加的插入程序对象。
“将可插部件606-608跟610和611分开”的决定可以基于各种标准。例如,部件606-608可能是同步插件程序,部件610和611可能是异步插件程序。另外,具有较短的针笔数据处理时间的插件程序可以由数据流C/D来处理,具有较长的针笔数据处理时间的插件程序可以由数据流F/G来执行。来自一个线程C/D的这些部件可以与线程F/G的部件进行交换。
“分开可插部件606-608和610-611的这两个集合”的一个优点是:这些可插部件由不同的线程来处理。这里,这些同步插件程序与这些异步插件程序之间的差异在于它们在其中执行的该线程、以及该调用序列(同步插件程序可以由实时针笔603正在执行的线程来调用;并且,在该数据包流已由这些同步插件程序来处理并被存储在输出队列605中之后,这些异步插件程序通常由该用户接口/应用线程来调用)。
在一些情况中,可能有从实时针笔部件603回到笔服务601或实时针笔服务602的公共通信。在其他情况中,没有从实时针笔部件603回到笔服务601或实时针笔服务602的公共通信。防止通信可以有助于来自这些部件的数据流。
在一些情况中,当通过按预定义序列将调用发送到这些插件程序来检索数据时,实时针笔部件603可以通知这些插件程序。接收这些通知的插件程序的该序列和类型可以由该开发者来控制。这些事件中的数据包数据可以由这些插件程序606-608和610-611中的任何一个来修改。
本发明的各个方面用于包括来自笔服务的数据包数据、关于显示器、写字板、笔等的变化通知、以及可以由该实时针笔来处理的其他数据集的各种数据类型。下文描述来自笔服务的数据包数据的运用,但这只是可以被用于实时针笔603的许多数据类型中的一种数据类型。关于以下内容,数据包数据被用作关于由该RTS处理的该数据类型的说明性例子,但将要被理解为:参考可以由该RTS来处理的更一般的数据。
实时针笔部件603也可以包括队列604和605。输出队列605可以保持时间针笔部件603处理的全部的数据包数据。一旦该数据包数据已从该插件程序那里返回,该数据包数据就被加入来自数据流E的输出队列605。然后,输出队列605可以由这些插件程序来使用(例如,异步的,并且通常包括墨水集合对象611)。通过将数据提取出来(数据流F)并从被保存在数据流G中的输出队列605内的数据建立墨水对象,可以发生这个情况。
输出队列605的尺寸可能是或可能不是固定的。如果是固定的,那么,在队列605满了之后,所有随后接收的数据包可能会丢失。如果不是固定的,那么,队列605的尺寸可以扩大,来接收附加的数据包。“保持固定尺寸的队列”的一个好处是:它将该数据待办事项限制到可以在合理的时期内被处理的数据待办事项。例如,如果该最终用户正在与该系统交互,并且,它变得无响应,那么,该最终用户通常暂停,直到该系统再次响应为止,从而允许该队列处理该待办事项,而不会丢失数据。此外,如果由于某个原因,创建过大量针笔数据,那么,队列605可以通过具有固定的尺寸来帮助消除部分的该数据。
输出队列605可以固定于有秩序地接收数据。另外,如下所述,数据可以被放置在序列的输出队列605中,以保持与实时呈现的同步。
输入队列604接收数据流B(或者,如果无实时针笔服务602,则是数据流A)中的信息。该输入队列提供过程,以便将数据输入到插件程序606-608。另外,针笔数据可以直接流到插件程序606-608。“将输入队列604作为数据流B与C(这里作为数据流Z)之间的中介物”的一个优点是:它允许在没有东西存在的地方插入被创建的针笔数据。
以下描述高级控制流。
a.实时针笔603将处理数据包数据推断为通过插件程序606-608来加以传递。
b.该实时针笔603将该被处理的数据包数据存储在输出队列605中。
c.该实时针笔603查看:输入队列604中是否有任何挂起的数据包数据。如果有数据,那么,从该输入队列挑出那个数据包数据并在以上步骤中加以处理。
d.该实时针笔603查看:笔服务601中是否有任何挂起的数据包数据。如果有,那么,从笔服务601挑出该数据包数据并在以上步骤中获得并处理。
e.这个过程在步骤c处重复。
以下描述对于“该实时针笔对象如何可以处理该写字板笔数据”的替换方法。可理解:只要进行较小的修改以下内容可以应用到图8、11和13,该修改是这些插件程序在该同步线程上的布置(从采用菊花链的每个插件程序到正被该实时针笔对象个别地调用的每个插件程序)。
a.实时针笔对象603首先核对其输入队列604上的插入式数据对象,然后核对来自写字板笔数据流B的插入式数据对象。
b.实时针笔对象603将C一个插入式数据对象发送到其同步插入程序集合中的对象606-608。每个同步606-608插件程序可以将数据加入到输入队列604或输出队列605。
c.一旦该插入式数据对象已被发送到同步插入程序集合的所有组成部分,该插入式数据对象就被放置在该实时针笔对象的输出队列605上。
d.然后,实时针笔对象603核对要处理的下一个插入式数据对象(来自输入队列604或数据流B)。
e.该实时针笔对象的输出队列605包含数据,而实时针笔对象603将一个插入式数据对象从其输出队列605发送到其异步插入程序集合610-611中的这些对象。每个异步插件程序610-611可以将数据加入输入队列604或输出队列605。但是,由于这些异步插件程序可以在该UI线程上运行,因此,被加入到队列604/605的数据与写字板笔数据流B中的该数据的其余部分或与实时针笔对象的输入队列604和输出队列605没有集合关系。
第四,该系统包括异步插件程序611(这里被表示为墨水集合对象)。这里,该墨水集合对象可以表示一个或多个插入程序对象。墨水集合和存储可以是发生于该UI或异步线程中的各种动作之一。一旦该数据包数据(或被修改的数据包数据)从同步插件程序606-608那里返回,它就被放置在实时针笔603的输出队列605中。然后,实时针笔603将该数据放置在输出队列605中。然后,该数据被转发插件程序610-611的下一个集合(在集合或链中)。这可以包括:将该数据转发墨水集合对象611——在那里,如该异步线程上的这各种插件程序所规定的,它可以被破坏/删除/再循环/释放。
第五,该系统可以包括为该系统提供基本功能的标准插件程序(可以被设计成运行于该同步线程或异步线程中的任何一个线程或这两个线程上)。这些标准插件程序可以包括动态呈现器608和姿态识别器610。当然,如果需要的话,可以用其他插件程序来取代这些标准插件程序。另外,在本发明的各个方面的一些实施中,没有标准插件程序最初可以被包括于该实时针笔。相反,可以鼓励开发者从第三方供应者中进行选择,和/或按需要来创建其自己的插件程序。
图7和图8提供图6的结构的另选版本。图7示出了笔服务701,它将针笔数据提供给实时针笔702。输入队列703(可能被或可能不被使用)将该针笔数据提供给同步插件程序801-805。这里,每个插件程序是插入程序集合的一部分。另外,这些插件程序可能是插件程序链的一部分。在这个最后的同步插件程序(实时针笔同步插件程序N 805)之后,该针笔数据(或被修改的针笔数据)被放置在输出队列709中,然后由随后的实时针笔事件异步插件程序710和808来处理。
关于图6和图7中的数据,如通过该RTS而被传送的每个数据集可能是单一数据集或一捆数据集,由于该数字转换器正按很高的速率来取样,因此,为效率起见,这些数据集被捆在一起。这些数据集提供各种事件的通知或通过该RTS来转发新信息。在一些情况中,可以删除该数据集。在数据集是一捆数据集r其他情况中,可以删除该捆中的单一数据集,同时,保留其他数据集。有效地修改这捆数据集。然后,实时针笔702可以将私人消息寄给它连在其上的窗口,并进行到该输入队列中的下一个数据集(或者,如果没有下一个数据集,则从该笔客户接口上的笔服务701所调用的该功能那里返回)。
图8A和8B示出了各种操作的数据流。图8A示出了正在笔服务701中被接收的颜色变化。实时针笔702包括同步插入程序集合809和异步插入程序集合810。该同步插入程序集合包括同步插件程序1 801、动态呈现器804和同步插件程序3 805。来自同步插入程序集合809的该输出被发送到输出队列709。异步插入程序集合810从输出队列709接收数据集,并在异步插件程序1-3811、812和813中处理它们。
对于图8A和8B的以下说明,使用数据包。但是,可理解:也可以使用其他数据集来传达信息。数据包只是可以被使用的该数据集类型的一个例子。这里,实时针笔702在输出队列709中有两个数据包A和B。当颜色变化CC被笔服务701接收时,数据包C当前正由动态呈现器804来处理。该颜色变化CC可以被立即转发到这些异步插件程序之一,并由该异步插件程序来加以处理。但是,这样做可能会引起混淆的情况——其中,在该颜色变化之前创建数据包A、B和C。相应地,可能只有在异步插入程序集合810对数据包A、B和C进行最后处理和最后呈现之后,才想要处理该颜色变化。
为了延迟颜色变化CC的该处理,插入程序集合809中的这些同步插件程序之一可以创建数据对象CC1并将它推入输入队列703。接下来,那个数据对象可以由输入队列来联机处理——颜色变化中的该结果由输出队列709中的CC2来表示。通过使用这个方法,可以利用先前接收的数据包来适当地命令用于更改笔划颜色的那个指令。
图8A示出了正由实时针笔部件702来处理的颜色变化的例子。但是,“创建用于由输入队列或输出队列来处理的对象”的这个方法有助于处理其他事件。
一些插件程序(包括(但不局限于)该动态呈现器)可以具有两个种类的属性——即,“其中变化立即生效的属性”对“从下一个针笔向下(笔划开始)中生效的属性”。可能会发生这两个种类之间的分离,这是因为各种原因,包括:技术考虑事项、对于用户经验和用户期望的关注等。例如,可以延迟笔划颜色变化,以便保存从该用户的观点来看这些笔划和事件发生的那个顺序。
图8B示出了处理数据包并且同时处理手势识别对象的实时针笔部件702。输出队列709包括许多数据对象——包括针笔向下事件(SD)、数据包(P)和针笔向上事件(SU)。当从同步插入程序集合809中的笔服务701那里接收针笔向上事件SU时,手势识别器尝试从一个或多个先前的数据包P中识别手势。如果数据包已被识别为手势,那么,手势识别器814生成手势识别对象GR,并将它放置在输入队列703中。对象GR的该手势识别然后通过这些同步插件程序来加以发送,并被发送到输出队列709。从输出队列709那里,该手势识别对象GR通过这些异步插件程序来加以传递,然后被破坏/删除/再循环/释放。通过输入插入程序集合809而创建和传递回来的该手势识别对象的好处是:在被转发到输出队列709之前,该处理允许该被接收的手势识别对象以便加以修改和/或删除。另外,通过具有由同步插入程序集合809和异步插入程序集合810来处理的手势识别对象GR,可以除去该针笔向下事件与该针笔向上事件之间的这些数据包,因为它们由该手势对象GR的存在来代替。另外,这些事件可以被忽视,与该手势相对应的该数据可能仍然与其他的插件程序顺流有关。一般而言,该系统管理“当该手势识别器存在时,哪些插件程序存在”,以便该行为与这些开发者的该所需结果一致,即,在它已被放置在那里之后,实际上从数据结构中除去正被忽视的该数据。
例如,在该GR到达它那里的时候,InkCollectingObject插件程序(可以建立数据包表格,然后在SU上创建墨水笔划)可能已经创建该笔划。所以,一接收到该GR,该InkCollectingObject就可以简单地删除那个以前创建的笔划。然后,另一个插件程序可以负责触发该GR上的那个适当的动作。
该同步和异步插入程序集合内的数据的处理虑及关于数据的各种处理技术。如果一些数据只与一些插件程序有关,那么,其他插件程序可以按需要来忽视或传递该数据。例如,第一个插件程序可以确定:数据包涉及显示器的不可使用墨水的那个区域。第二个插件程序可以用各种方法来处理这些数据包,这些方法包括:
a.忽视来自该第一数据包的该通知,
b.吸收该通知并使其无效,以便不将该数据包传给随后的插件程序,或者,
c.规定:它对该通知不感兴趣(例如,通过设置指出该第二个插件程序对这些类型的数据包感兴趣的程度的属性)。这里,该实时针笔部件可以跳过该第二个插件程序,因为它已规定:它对该数据包不感兴趣。
通过在不需要的时候除去功能调用的开销,这第三个途径C可提供性能好处。
通过调用该AddCustomStylusDataToQueue方法,可以将自定义针笔数据加入该实时针笔对象。如果响应于对其IstylusSyncPlugin方法之一的调用从同步插件程序那里作出对AddCustomStylusDataToQueue方法的调用,那么,该自定义针笔数据按确定方式而被加入到写字板笔数据流;否则,它按非确定方式而被加入。如果RealTimeStylus对象被禁止,那么该AddCustomStylusDataToQueue方法发出一例外。
自定义针笔数据可以在三个地方中的一个地方被加入该实时针笔对象的队列。
a.当该队列参数被设置为“输入”时,该自定义数据在来自该写字板笔数据流的新数据之前被加入该实时针笔对象的输入队列,并被发送到该同步插入程序集合。
b.当该队列参数被设置为“输出”时,该自定义数据在当前正由该同步插入程序集合来处理的该数据之后被加入该实时针笔对象的输出队列。
c.当该队列参数被设置为“输出立即”时,该自定义数据在当前正由该同步插入程序集合来处理的该数据之前被加入该实时针笔对象的输出队列。
在以上每种情况中,在前述插件程序所加入的数据之后加入由该同步插入程序集合中的随后的插件程序所加入的数据。
当自定义针笔数据对象和插件程序通过其IStylusSyncPlugin.CustomStylusDataAdded或IStylusAsyncPlugin.CustomStylusDataAdded方法来接收自定义针笔数据时,该数据被加入该队列。
该动态呈现器和这些手势识别器对象可以将自定义针笔数据加入该队列。
该实时针笔对象调用线程上的IStylusSyncPlugin.CustomStylusDataAdded方法,它从该线程那里接收对其AddCustomStylusDataToQueue方法的调用。
该实时针笔对象可能被或可能不被配置成集合墨水。在它不集合墨水的情况,可以使用该实时针笔来将墨水数据转发到墨水集合对象。该墨水集合对象可以采取插入该实时针笔的输出的墨水集合插件程序的形式。
墨水分析或笔迹识别不是该实时针笔对象的功能。当该墨水集合插件程序集合和创建墨水时,或者当想要识别该墨水时,可以将该墨水拷贝到RecognizerContext或Divider对象。
如上所述,墨水可以被显示一次以上。第一次可以利用该动态呈现器来呈现墨水。在墨水已被集合在墨水集合对象中之后,第二次可以利用静态呈现器来显示墨水。这可以许可:当从该墨水集合对象那里接收该墨水时,使用其他类型的呈现器来呈现它。例如,可以具有彩色墨水作为该静态呈现器的一部分。对于该同步线程而言,向该动态呈现器推行这套效果可能会工作量太大了。相应地,可以创建呈现器,并使它附加到该异步线程。另外,可以忽视该默认动态呈现器,创建自己的动态呈现器,并将它插入该同步线程。也可以创建动态呈现器,该动态呈现器通过如面向对象方法中所使用的多形、聚集或保留而在内部再使用标准动态呈现器。
也可以将该异步线程上的这个新的呈现器再用作该静态呈现器,或者可以为此目的来创建新的呈现器。例如,可能想要呈现墨水,好象用炭笔或其他笔尖来绘制一样。另外,可以创建显示墨水的呈现器,好象它随时间的推移而经常更改颜色(迅速地或缓慢地),以表示物理墨水如何变干。而且,可以创建利用循环颜色(如同彩虹中那样)来显示墨水的呈现器,以加亮显示该墨水。明确地说,通过创建预订该StylusDown、Packets和StylusUp通知的同步插件程序,可以创建动态呈现器插件程序。然后,当正在绘制该笔划时,该插件程序可以呈现它。这个新的呈现器可以处理墨迹作图、以及各种选择机制。
动态呈现器插件程序是当该写字板笔数据正由该实时针笔对象来处理时实时地显示它的对象。以后,对于诸如形式刷新的事件,该动态呈现器插件程序或墨水集合插件程序可以重画该墨水。
该动态呈现器对象实现该IstylusSyncPlugin接口。该动态呈现器另外还可以实现异步接口。当正在绘制该墨水时,该动态呈现器对象实时地呈现它。默认的情况是:当调用该刷新方法时,该动态呈现器对象重画当前正连同其他以前集合的笔划(将会对应于DynamicRenderer的CachedData)一起集合的那个笔划。可能存在该刷新行为的其他开销,它们包括用于(例如)利用剪取区域来约束绘图的该行为的参数,以便在给定的形状以外不呈现墨水。
各幅图中示出了这一点(该动态呈现器对象可以临时高速缓存墨水数据)。当该动态呈现器对象接收对其IStylusSyncPlugin.StylusUp方法的调用时,响应于对于该笔划的StylusUpData对象,它高速缓存该笔划数据,并将自定义针笔数据加入输入队列。该CustomStylusData对象的CustomDataId属性被设置为DynamicRendererCachedDataGuid值,并且,该CustomStylusData对象的Data(数据)属性包含DynamicRendererCachedData对象。然后,一旦已顺流呈现该墨水,就可以清除该动态呈现器的该关联的数据的高速缓存。另外,刷新该墨水(重画被存储在CachedData中的当前笔划和数据)可能不总是清除该动态呈现器的墨水笔划的高速缓存,因为那些墨水笔划可能还没有传递通过该墨水集合对象并由该墨水集合对象来存储。
图9和图10示出了用于建立本系统的各个方面的过程。在图9步骤901中,例示实时针笔部件。在步骤902中,例示同步和异步插件程序。这可能包括或可能不包括动态呈现器和/或手势识别器903的例示。在步骤904中,插件程序被加入插入程序集合。在步骤905中,启用该实时针笔。在步骤906中,通过该实时针笔来接收笔数据。
图10示出了用于使用该实时针笔的过程。在步骤1001中,由该RTS来接收数据包。这可能包括或可能不包括该输入队列的该操作。该输入队列在任何时候都支持任意数据的插入,以便它将经过该同步集合。在这个例子中,将数据放入该输入队列的这个唯一的部件是笔服务——这是(例如)“调用笔客户接口的RTS的实施上的功能”的结果。
在步骤1002中,该数据包进入该同步插入程序集合。对于系统(例如,图8中的系统),这个步骤可能意味着:将该数据包转发到这些插件程序中的第一个插件程序。该实时针笔调用适于集合(或者,如果链存在,则是链)中的第一个插件程序上的该特定数据包数据的那项功能。在许多情况中,这个部件具有“修改该数据”或“不理会它”的选项。当该部件完成其操作时,它下一个插入程序对象上调用相同的功能,等等。
在步骤1003中,该数据包前行通过该同步插入程序集合(或链)。这可能包括或可能不包括如步骤1004中所示那样被转发到手势识别器或动态呈现器的数据包。如果使用动态呈现器,那么,它可以开始在存储器中累积关于光标向下事件(也被称作“笔向下事件”)的数据包数据,并在屏幕上开始呈现它们(该动态呈现器的操作)。关于光标向上事件(或笔向上事件),该动态呈现器可以清除其存储用于下一个光标向下事件。
如果使用手势识别器,那么,该手势识别器可以倾听光标向下事件,并开始在其自己的存储器(例如,存储器807)中累积数据。当笔划累积时,该手势识别器将这些笔划传入识别器,并且,如果这些笔划对应于所需样式(或手势),那么,a)该手势数据被加入到输出队列,并且b)该存储器被腾空,累积再次开始——下一个光标向下事件传递通过该队列。这里,注意,手势可以包括一个或多个笔划。图14(以下更详细地加以描述)示出了如何可以根据图10中的该过程来处理多个笔划手势。
插件程序应该或可以了解先前的笔划达到什么程度取决于该插件程序的目的。
a.在一个范例情形中,正在倾听手势的插件程序可能负责响应于该手势来执行动作。它可能不需要知道关于这些笔划的任何事。例如,如果窗口中的“圆圈”手势意味着关于该应用程序的“删除”,那么,接收该手势的该插件程序将会仅仅把“删除”键击发送到该窗口。关于这个范例情形,墨水甚至可能没有正在该窗口中被集合;它可能是包含文本的窗口,并且,该RTS构架在此情况下可以被安排成允许笔划数据仅仅落空——永远不被集合。这样,该插件程序不需要高速缓存该笔划。
i.在另外情况中,以上的“解释器”插件程序可能生成其自己的通知,以下游插件程序将会知道“解释过该手势”,因此不坚持其笔划。
b.在另一个范例情形中,该插件程序可能正在执行墨水集合和编辑操作。这一点的典型例子可能是该墨水集合器对象的模式(墨水和手势模式)——其中,所有笔划潜在地是手势,并且,如果它们被视作手势,那么,该笔划随后被删除。这样,如果笔划以“被解释为手势”而结束,那么,该插件程序应该高速缓存那些笔划,以便能够发现并删除它们。
在这两个范例情形中,单一笔划手势与多笔划手势之间的该区别确实不要紧;该应用情形可以要求多笔划手势(例如,箭头)——在此情况下,以上的两个范例插件程序将出于必要性而了解多笔划手势。
接下来,在步骤1005中,在被同步插件程序的集合处理之后,该数据包进入该输出队列。如前所述,在处理被发送给它的这些对象中的每个对象的过程中,插件程序的该集合可以修改删除并/或取代该数据包。假设“这些同步插件程序没有一个删除过该数据包”,则执行步骤1005。
在步骤1006中,该数据包前行通过集合中的该异步插件程序。
动态呈现和湿墨水
该系统提供“迅速而有效率地处理针笔数据”的能力。为了使电子墨水表现得象真墨水,该电子墨水需要看起来如同真墨水那样容易地从针笔尖端流出。该墨水流动中的小中断或延迟对该电子墨迹作图经验而言是不利的。以下描述用于确保“电子墨水看起来从该尖端流畅地流出”的各种途径。“湿墨水”被认为是一种能力,用于控制“在集合墨水之后,该动态呈现器拥有静态呈现多长时间”。为了帮助处理该动态呈现器中的墨水使用寿命的管理,可以使用通知(这里被称作DynamicRendererCachedData),以允许墨水集合插件程序从该动态呈现器中释放该被高速缓存的(或湿)墨水。
可以创建各种不同类型的动态呈现器。例如,动态呈现器可以将墨水呈现为已由半透明的、基于水的颜料(也被称作“水彩颜料”)来创建,而不是将墨水呈现为已由细点笔或粗点笔来创建。此外,可以创建动态呈现器,该动态呈现器将墨水呈现为已由炭笔针笔来创建。另外,该动态呈现器可以呈现墨水,以便它不被固定,但有规则地更改颜色和/或移动颜色。例如,该动态呈现器可以将墨水呈现得看起来好象聚结成该所需墨水形式的小滴墨水或灰尘,好象最后一起移动来形成所需墨水的小蠕虫,或者好象更改颜色和形状的墨水。
该动态呈现器显示墨水的形式可以等同于由与该RTS的异步线程关联的对象以后呈现的形式。另外,在该动态呈现器所呈现的墨水与跟该RTS的该异步线程关联的最后的墨水显示之间可以存在关系。例如,该动态呈现器可以按第一种色调或形状来示出墨水——只是供该异步线程上的该插件程序以后修改成第二种色调或形状。对于该用户而言,这可能看起来好象墨水或颜料在从针笔流出时变干。
关于动态呈现和湿墨水的以下说明可以被应用于图6-7。出于解释的目的,参考图6。图7中的该布置同样适用,并且,以下说明也想要包含图7。
参考图6,数字转换器输入从笔服务601进入,并达到实时针笔603。该实时针笔通过多个同步插入程序对象606-608来传递该数字转换器输入,并将该结果存储到输出队列605中。可以通过描述对象606-608之间的链接的接口(例如,IStylusSyncPlugin),来连接这些对象606-608。然后,对象610-611的该异步插入程序集合从输出队列605接收该输出,并开始处理它。例如,墨水集合对象611可以从该输出队列中提取数字转换器输入,并将它存储为墨水。当实时针笔部件603将该数字转换器输入(作为被修改的或未被修改的)传递到动态呈现器608时,发生该数字转换器输入的动态呈现。当该数字转换器输入被存储在墨水集合对象611内的该墨水存储器中时,发生该数字转换器输入(作为被修改的或未被修改的)的静态呈现。
可能会发生的一个事项是:在动态呈现608之后,并且在该数字转换器输入被存储在墨水集合对象611内之前,墨迹作图表面可能会变得无效。该数字转换器输入达到墨水集合对象611之前。最后得到的该用户经验将会被显示墨水消失。该用户可以相信:他或她需要再创建该墨水,然后花时间这样做,从而导致重复的墨水最后被存储。这个可见停顿是由于该墨水没有准备好向用户示出或在延迟后被示出。
为了避免这个消失墨水情形,可以在动态呈现器608与墨水集合对象611之间建立通信协议。动态呈现器608可以继续将数字转换器输入高速缓存在可见存储器609中,直到它被墨水集合对象611告知(例如,当该数字转换器输入已被存储在墨水存储器612中时):它可以释放该数字转换器输入。
出于这里的目的,动态呈现器608中的数字转换器输入的暂时高速缓存609当前被称作“cacheddata(高速缓存的数据)”。湿墨水是“在数字转换器输入被存储在墨水集合对象611中之前,供该系统呈现墨水”的能力。
图11示出了该墨水集合对象如何提醒该动态呈现器来释放其高速缓存数据。动态呈现器1201包括可见存储器1202。墨水集合对象包括墨水存储器1204。一旦动态呈现器1201已将针笔数据存储在可见存储器1202中,它就将一个对象输出到输入队列1205中。在查看笔服务701之前,该实时针笔(例如,702)探查输入队列查找要处理的下一个数据。出于这里的目的,被增添到该输入队列中的该对象被称作“DynamicRendererCachedData”。然后,该对象由实时针笔702来(具有或没有附加的处理),并将它输出到输出队列1206中。其间,墨水集合对象1203正按出现在输出队列1206中的顺序来处理这些被接收的针笔输入数据包。当墨水集合对象1203遇到来自动态呈现器1201的该对象(这里是该DynamicRendererCachedData对象)时,它执行以下动作:
a.创建与该动态呈现器所呈现的该笔划相匹配的适当的相关笔划;
b.将存在于该动态呈现器笔划上的这些绘图属性应用于将要被呈现的笔划;以及,
c.将释放通知发送到动态呈现器1201。这个通知可以涉及:在该“动态呈现器”上执行方法,并传递参数。
根据“在所有笔划已被移出输出队列之前,是否已发生绘图属性修改的该同步”,以上的步骤B可能会或可能不会适当地执行。图8A涉及用于使绘图属性变化与以前接收的数据包同步的过程。
可以根据开发者的愿望而在该系统中设置这些绘图属性,或者,在其他方法之中,可以在被传递到墨水集合对象1203的该对象中提供这些绘图属性。该释放通知可能是动态呈现器1201所提供的接口上的调用。这里,该通知可能是ReleaseCachedData。
图12示出了用于处理湿墨水的替换方法。图12包括将针笔数据发送到实时针笔702的笔服务输入701。输入队列703可以处理输入并使这些输入排入队列——实时针笔事件汇流点的结果被放置在输出队列709中。图12包括附加的队列1101。这个队列处理来自动态呈现器1102的这些结果,该动态呈现器1102已与其他实时针笔事件汇流点A 1103和B 1104分开。这里,这个途径对付可能会发生的该事项——其中,实时针笔事件汇流点A 1103和/或B 1104减缓从该针笔流出的墨水的出现。在图12中的该系统处理其他事件汇流点A1103和B 1104之前,它处理针笔数据的动态呈现。即使事件汇流点A 1103和B 1104在去往墨水集合对象1105的途中的针笔数据的该处理过程中可能仍然会引起延迟,动态呈现1102事件汇流点也可以在接收针笔数据时继续处理它。这里,针笔数据一被动态呈现器1102呈现,该输出就被发送到另外的队列1101——在那里,它随后由实时事件汇流点A 1103和B 1104来访问。注意,可以通过任何一种方法来执行“如何访问实时事件汇流点A 1103和B 1104(一个调用另一个,或者两者被附加的队列1101调用)”的过程。
图13示出了关于“如何确保湿墨水从针笔流出”的另一个方面。这里,次级实时针笔对象存在于单独的线程中。笔服务701将针笔数据输出到实时针笔部件1301。输入队列1302将针笔数据提供给动态呈现器1303。其他同步插件程序可能与或可能不与实时针笔部件1301关联。任选的同步插件程序包括手势识别器1304和其他同步插件程序1305。来自这些同步插件程序的输出被转发到输出队列1306。这里,实时针笔部件1307从实时针笔部件1301那里被连接到来处实时针笔部件1301的输出队列1306。从实时针笔部件1301的观点,该实时针笔部件1307及其关联的同步插件程序1309-1313以及异步插件程序1312-1313担当异步插件程序。这些数据包(但是,被实时针笔部件1301的这些同步插件程序修改)被转发到关于实时针笔部件1307的该同步插入程序集合。例如,对于实时针笔部件1307的同步插入程序集合包括同步插件程序A 1309、同步插入程序部件B 1310和(如果以前没有被使用过的话)手势识别器1313。可理解:手势识别器1313是可能与对于任何实时针笔部件的同步线程或异步线程相关联的一种类型的插件程序。将该手势识别器1313与关于实时针笔部件1307的同步插入程序集合联系起来是出于说明的目的。
实时针笔部件1307的同步插入程序集合的输出被转发到输出队列1311。然后,异步插入程序对象1312-1313可以处理输出队列1313中的这些数据包。再有,甚至当阻止该应用程序时,墨水也被动态地呈现,并从该笔中流畅地流出。
为参考起见,注意:这各种插入程序部件可以用链栓在一起,而不是在插入程序集合中相互跟随。这里在图13中示出一个例子——其中,同步插入程序部件A 1309被链栓到同步插入程序部件B 1310。当然,将插入程序组件链栓一起或将它们集合在一个集合中的方法可以交替或互相添加地使用,以便按本发明的各方面确定插入程序组件的地址。
手势识别
手势识别尝试确定“是否已作出手势”,并适当地处理它。例如,手势识别器610负责观察数字转换器输入,并且类似于动态呈现器608来将手势识别结果增添到该输入队列中。图8B描述如何可以利用同步和异步插入程序集合来执行手势识别。那个说明有关于该手势识别对象的该操作。
手势识别器610可以使用算法。这里,该手势识别器可以使用排列算法来识别多笔划手势。例如,当已设置涉及该最大笔划数量的属性时,该手势识别器回顾那许多笔划。例如,如果该属性被设置为2,那么,该手势识别器回顾最新近的2个笔划,从而试着将它们识别为手势。这可以导致多个识别调用。但是,这个途径消除恒定延迟,用于必须等候手势识别器在最后一个笔划之后开始处理。
图14示出了“手势识别器回顾有多远来获得手势的各个部分”的例子。这些结果可以被存储在对象(这里,例如,是命名的GestureRecognitionData)中。这些结果可以被增添到该实时针笔输入队列中。
一旦墨水集合对象611接收该手势对象(这里是GestureRecognitionData),它就从墨水存储器612中除去关于该手势的这些笔划,并响应于该手势来实行这些适当的动作。
如上所述,为了执行手势识别,该系统可以响应于完成该手势的数据(例如,关于该“轻敲”手势的StylusUpData对象),来将SystemGestureData对象加入该输入队列。
利用各种接口,该手势识别器可以作为对象来加以执行。例如,该手势识别器对象可以执行IStylusSyncPlugin和IStylusAsyncPlugin接口。
当该手势识别器对象识别手势时,它响应于关于该笔划的该StylusUpData对象,来将自定义针笔数据加入该输入队列。该CustomStylusData对象的CustomDataId属性被设置为该GestureRecognitionDataGuid值,并且,该CustomStylusData对象的Data属性包含GestureRecognitionData对象。
默认的情况是,该手势识别器对象只识别单一笔划手势。该手势识别器对象可以被设置成识别多笔划手势(例如,见图14)。关于多笔划手势,响应于关于该手势的最后一个笔划的该StylusUpData对象,来将该CustomStylusData对象加入该输入队列。当识别多笔划手势时,可以接收用于重叠各个笔划集的通知。例如,第一和第二个笔划可以共同被识别为一个手势,第二个笔划可以本身识别为一个手势,第二和第三个笔划可以共同被识别为另一个手势。
如果正将该手势识别器对象用于多笔划手势识别,那么,可以使用串联的实时针笔模型,并使该手势识别器对象附加到次级实时针笔对象,以便减少该实时线程上的延迟,但防止手势识别受到该用户接口线程上的延迟的影响。
另外,可以用三种方法来创建识别笔迹手势或其他对象的自定义手势识别器插件程序。
a.通过将该笔划信息传递到现存的“识别器”对象,并使用该AddCustomStylusDataToQueue方法来将这些结果加入该笔数据流。
b.通过在自定义插件程序内执行该识别,并使用该AddCustomStylusDataToQueue方法来将这些结果加入该笔数据流。
c.通过利用按菊花链方式调用该标准插件程序的自定义插件程序来包装标准手势识别器插件程序。利用这个方法,通过将空中数据包“转化”为Packets(数据包)、将Cursor-In-Range“转化”为StylusDown、并将CursorOutOfRange“转化”为StylusUp,开发者可以执行空中手势识别。
当系统手势被该系统识别时,该实时针笔对象接收关于它们的数据。以下表格描述:相对于其他笔数据这些SystemGestureData对象发生在该笔数据流中的什么地方。以下清单起说明的作用,而不是包括一切的。在不脱离本发明的范围的前提下,可以结合本发明的各个方面来使用其他手势。
SystemGesture说明
Tap 在StylusDownData对象之后,在StylusUpData对象之前。
DoubleTap 在StylusDownData对象、关于该Tap系统手势的
SystemGestureData对象、以及StylusUpData对象之后,在
第二个StylusDownData对象之前。
RightTap 在StylusDownData对象、以及关于该HoldEnter系统手势
的SystemGestureData对象之后,在StylusUpData对象之
前。
Drag 在StylusDownData对象之后,在StylusUpData对象之前。
RightDrag 在StylusDownData对象之后,在StylusUpData对象之前。
HoldEnter 在StylusDownData对象之后,在StylusUpData对象之前。
如果该用户开始Drag或RightDrag系统手势,那么,这个
系统手势不被识别。
HoldLeave 可选
HoverEnter 在低平均速度的几个InAirPacketData对象之后。在接收该
HoverEnter系统手势之前,可能有显而易见的延迟。如果
该实时针笔对象在该系统手势的时候被附加到直接在该
笔下的该窗口或控件,那么,该实时针笔对象只接收该数
据。
HoverLeave 在关于该HoverEnter系统手势的SystemGestureData对象
以及足够的平均速度的几个InAirPacketsData对象之后。
在接收该HoverLeave系统手势之前,可能有显而易见的
延迟。如果该实时针笔对象在该系统手势的时候被附加到
直接在该笔下的该窗口或控件,那么,该实时针笔对象只
接收该数据。
同步和异步过程
当例示实时针笔实例时,可以例示执行线程。该执行线程可以被分成同步对象和异步对象。这些同步对象通常与起源于笔服务部件的数据包同步地进行操作。这些异步对象通常被分组为不必总是结合墨水笔划和/或起源于笔服务部件的其他数据包来加以执行的对象。这两个线程的分离允许动态呈现器对象与数据包的接收同步地来迅速处理这些数据包,并允许的接收有其他插入程序对象,这些插入程序对象(虽然仍然很重要)甚至可以带有对这些原始数据包的接收的轻微延迟来加以正确的处理。
在这个新的线程上执行同步插件程序的集合对该实时针笔实例例示过这个新的线程。可以在用户接口线程中执行异步插件程序的集合。
该实时针笔线程可以意在用于计算上减轻工作量,以便墨迹作图(数据包排队和动态呈现)通常是易响应的和流畅的。所以,只有计算上轻松的处理通常应该利用关于这些同步插件程序的该线程来加以执行。
该用户接口线程(通常与该输出队列的该输出相关联)通常由要求计算量大的活动的异步插件程序来使用。为了起到帮助的作用,在该实时针笔线程与该用户接口线程之间提供队列的体系结构,以便坚定抵抗该用户接口(UI)线程中的临时阻塞。该UI线程可能是或可能不是在该实时针笔线程上被集合的数据包和其他数据的最后目的地。注意,另外的体系结构可以更好地处理计算量大的活动,从而不容易迫使开发者在阻止笔线程与用户接口线程之间妥协。例如,如这里所述的串联设计允许该线程分离更好地处理不同的活动。
如果该手势识别器被确定或预期由于预期的繁重的手势识别活动(例如,将与笔划进行比较的大量被接受的手势)是缓慢的,那么,该手势识别器可以在同步线程上加以执行,或可以在该异步线程上加以执行。该手势识别器对象可以既具有同步插入程序接口、又具有异步插入程序接口,以便为开发者提供“从任何一个或这两个线程中利用该对象”的灵活性。这个能力不局限于该手势识别器。该动态呈现器或任何其他的插件程序能可选地地支持任何一个或这两个队列中的使用。可理解:所有插件程序可能具有或可能不具有同步接口、异步接口、或两者,以便如果该插件程序支持这一点,则允许开发者将该插件程序放置在同步集合中或异步集合中或两者中——取决于该开发者预期关于该插件程序的好位置是在哪里。
实时针笔对象提供对该写字板笔数据流的实时访问,并可以在其自己的线程上运行。同步插件程序通常可能会或可能不会在该实时针笔对象的线程上运行,而异步插件程序通常可能会或可能不会在该应用程序的用户接口(UI)线程上运行。通过将对于要求对该数据流的实时访问并且在计算量较轻的任务(例如,动态呈现)的插件程序放置在同步线程上,可以将同步线程与异步线程分开。对于不要求对该数据流的实时访问的任务(例如,墨水集合)的插件程序可以被放置在该异步线程上。
某些任务可能要求大量计算,但仍然要求接近于对该写字板笔数据流的实时访问(例如,多笔划手势识别)。用于处理这些任务的插件程序可以在一个或另一个线程上被分组,或者可以是如图12和13所示的串联的实时针笔对象的一部分。
串联
在许多方面,实时针笔实例是封装延伸性和政策的线程宿主。图13示出了多个同步线程如何可以一起运作的例子。手势识别器可以被放置在位置1304处的同步线程上,或者可以被放置在位置1313处的同步线程上。
如果有该开发者想要按多线程方式来连接的多个功能性,那么,该开发者可以串联多个实时针笔实例,并插入其功能性,作为同步插件程序。
提出这个特点的该特殊情形是:实现“真正不可中断的”墨迹作图。当该开发者尤其对多笔划手势感兴趣时,该手势识别器有时可能会引起重大的等待时间来获得识别结果。所以,该手势识别器可能不在该动态呈现器所在处的实时针笔的同步集合上,因为它有可能阻碍动态呈现。也可以利用具有异步插件程序的该集合的该墨水集合对象来定位该手势识别器。
如图13所示的该系统是有益的——其中,想要将计算量大的操作与该手势识别器或关于操作(包括(例如)访问数据库、寄到web服务器、刷新屏幕、等等)的其他线程分开。在“手势识别器是该‘真正不可中断的’经验的不可分割的一部分”的情况中,可以让该手势识别器在其自己的线程(即第二个实时针笔线程)上运行。
实时针笔可以通过执行异步接口来支持这个用法,从而允许它仅仅表现为异步插入程序实例。以下描述一个实时针笔如何可以被加入另一个实时针笔。以下提供可能会或可能不会被执行的许多选项。
1.当实时针笔被加入异步插件程序的集合时,该系统可以限制关系,以便可以不增加其他的异步插入式接口。
2.可以沿多个维度来串联不同数量的实时针笔对象。例如,多个RealTimeStylus对象可以被直接连接到单一“父”RealTimeStylus;或另外,这多个RealTimeStyluses可以被顺序地连接,以便每个串联到下一个中;或作为另选,这些RealTimeStylus对象可以在上述配置的组合中被连接。为简单性或可靠性起见,实施者可以选择约束这些组合。
3.当相同的实时针笔实例从多个实时针笔父辈被加入异步插件程序的多个集合时,该串联实时针笔可以发挥正常的作用。另外,该串联(子)实时针笔实例可以停止发挥作用,并将ErrorData对象插入该队列。该ErrorData对象可以是对下游对象的指示:该数据中有错误;或者,在处理该数据的同时,先前的插件程序遇到过错误。当然,这只是用于处理错误的一个方法。也可以使用其他方法。
注意,虽然一项实施可以将异步插入程序集合再用作关于串联的集合点,但另外的实施可以具有用于连接串联的RTS的专用连接点,从而允许该串联中的每个RTS具有其自己独立的同步和异步插件程序组。
可理解:该ErrorData对象的存在可能与串联无关。所以,可以关于单一实时针笔部件以及用串联的实时针笔部件来生成该ErrorData对象。
动态插入程序集合修改
可以修改该实时针笔上的这些同步和异步插入程序集合,而无须为性能好处来禁止使用、然后再启用该实时针笔。这样,不可保证:在该实时针笔范围处执行“被启用的”或“被禁止的”操作。
为了确保插件程序可以进行初始化和清除的定时,可以对从这些插入程序集合中被动态地插入或除去的插件程序进行“人工的”(意味着:不产生于对启用和禁止的真实的客户代码调用)RealTimeStylusEnabled和RealTimeStylusDisabled调用。
以下描述当增加或除去插件程序时可能会发生的某些行为。
·当插件程序被加入被启用的实时针笔实例时,可以对这个插件程序进行人工的RealTimeStylusEnabled调用;
·当插件程序被加入被禁止的实时针笔实例时,可能不会发生什么情况;
·当从被启用的实时针笔实例中除去插件程序时,可以对这个插件程序进行人工的RealTimeStylusDisabled调用;以及,
·当从被禁止的实时针笔实例中除去插件程序时,可能不会发生什么情况。
保持这些关系的使方法可能会或可能不会包括:每当它使得实时针笔启用调用时,递增计数器。每当它获得实时针笔禁止调用时,递减这个计数器。当该计数器是1时,这个插件程序发挥作用。当该计数器变得大于1时,这个插件程序引起例外,并禁止其功能性。当该计数器降回到1时,这个插件程序保持被禁止。当该计数器再次降回到0时,该插件程序只是再启用自身。可以使用其他途径。
错误传播
设计时间
在开发环境(例如,微软公司生产的Visual Studio.NET)中,开发者可以在发出的任何例外处被打断,而不管是否它已被捕获或未利用“尝试捕获”(a trycatch)来捕获它。所以,出于“检测该RealTimeStylus构架的无效配置”的目的,错误报告是直截了当的。
运行时间
该错误报告/传播事项对于运行时间错误而言可能会变得困难,因为实时针笔和同步插件程序正在不同于该UI线程(应用线程)的该实时针笔线程(墨水线程)上运行。如果同步插件程序发出例外,那么,它可以由该实时针笔来捕获,但该例外没有进一步处理,因为它在该实时针笔线程(墨水线程)上,并且,该控制流的起源是该实时针笔。将该错误传播到该用户接口线程并允许该客户代码得体地处理该错误可能会有困难。以下描述解决方案。
该.NET标准错误处理要在发生例外时从这些插件程序中激发事件,并让该UI线程中的该开发者的错误处理代码侦听这个事件。这对于“实时针笔”而言不起作用,尽管因为当插件程序激发事件时,有一种可能性:由于该排队,引起过该例外的该数据可能还没有到达该UI线程。实行得体的错误处理,而该错误处理代码而没有例外发生的环境(即该坏数据、以及前面和后面的数据)——这是具有挑战性的。这个方法只是对于简单的错误处理(例如,引起错误对话,以及终止该应用程序)而言有好处。
用于在该实时针笔构架内实行错误处理的这些适当的地方在这些插件程序(同步的或异步的)中,因为该插件程序是在该开发者的控制之下的唯一代码块。
从同步插件程序中发出例外的情况实时针笔线程(墨水线程)不应该立即停止发挥作用,因为这使“在该UI线程(应用线程)中实行错误处理”成为不可能(例如,为了错误处理这些队列需要保持完整无缺)。另外,一个插件程序认为是无效的输入对于另一个插件程序而言可能是完全有效的。
图15示出了可能的解决方案。这里,通过作为ErrorData对象的这些队列来再发送例外信息。可以在插件程序中实行错误处理。可以通过为插件程序而创建的该数据流(即该队列),来处理该例外信息。
如图15所示,实时针笔603捕获来自插件程序606-608的所有例外,并创建ErrorData对象。以下示出用于识别错误的过程:
a.如果在关于这些同步或异步插件程序的该接口上的错误方法中发生例外,那么,不创建ErrorData对象,以避免由于调回到该例外起源插件程序中引起的无限循环。
i.另外的方法是:在引起过该例外的该实际数据之前,立即通过该集合中的这些剩余的插件程序来传递该ErrorData对象。
b.如果在关于这些同步或异步插件程序方法的接口上的其他方法中发生过例外,那么,在引起过该例外的该实际数据之前,该ErrorData对象首先可以被立即传递到该例外起源插件程序本身,然后通过集合中的这些剩余的插件程序来加以传递。
c.如果该例外在这些同步插件程序中发生过或者被传递到异步插件程序,那么,该ErrorData最后被排入该输出队列中。
d.在该ErrorData通过该集合之后,引起过该例外的该数据传递通过该集合中的这些剩余的插件程序。
通过专用方法(例如,IStylusSyncPlugin.Error方法或IStylusAsyncPlugin.Error方法),可以通过该插入程序集合来传递该ErrorData对象。
更具体地说,当插件程序抛出例外时,中断正常数据流。该实时针笔对象生成ErrorData对象,并调用抛出过该例外的插件程序的IStylusSyncPlugin.Error或IStylusAsyncPlugin.Error方法、以及那个集合中的这些剩余的插件程序的该IStylusSyncPlugin.Error或IStylusAsyncPlugin.Error方法。如果抛出过该例外的该插件程序是同步插件程序,那么,该ErrorData对象被加入该输出队列。然后,实时针笔对象恢复该原始数据的正常处理。
如果插件程序从其错误方法中抛出例外,那么,该实时针笔对象捕获该例外,但不生成新的错误数据对象。另外,可以根据该开发者的该实施或愿望来产生新的错误数据对象。在这个另选方法中,该实时针笔随后可以通过限制递归数量来减少任何被创建的循环,或者,它可以完全忽视该风险。
关于同步插件程序所增加的自定义针笔数据,在于创建过该错误数据的该例外前面被加入该“输出立即”队列的任何自定义针笔数据之后,并且在被该同步插入程序集合中的随后的插件程序将任何自定义针笔数据加入该“输出立即”队列之前,该错误数据被加入则输出队列。如果任何的这些同步插件程序响应于该错误数据将自定义针笔数据加入该“输出立即”队列,那么,在紧接着该错误数据之前加入该数据。如果任何的这些同步插件程序响应于该错误数据来将自定义针笔数据加入输出队列,那么,在紧接错误数据之后加入该数据。
该实时针笔对象调用从那里抛出该例外的该线程上的该IStylusSyncPlugin.Error方法。
被管理/未被管理的举例说明
图16示出了用于植入本发明的各个方面的各种途径。该系统可以包括由C#被管理的对象的集合来包装的COM对象。另外,可以使用任何面向对象的语言(包括Java、C++等)。
图16示出了存在于被管理和未被管理的空间中的实时针笔部件。图16包括动态呈现器、异步插件程序Y、异步插件程序和手势识别器。
笔服务1601将针笔数据发送到实时针笔部件1602——其输入队列1603和输出队列1604在该未被管理的代码区内。针笔数据被传递到该被管理的代码区内的实时针笔部件1605。
动态呈现器是附于该实时针笔部件的第一个同步插件程序。在该未被管理的空间中,具有其高速数据缓存1616的动态呈现器1608被附加到实时针笔部件1602。同样,在该被管理的空间中,具有其高速数据缓存1617的动态呈现器1615是关于实时针笔部件1605的同步插入程序集合的一部分。在该同步插入程序集合中的下一个同步插件程序是同步插件程序1607。同步插件程序1607紧跟在关于RealTimeStylus部件1605的同步插入程序集合中的动态呈现器之后。由于同步插件程序Y 1607只存在于被管理的空间中,因此,同步插入式包装1618允许未被管理的RealTimeStylus部件1602越过该被管理/未被管理的边界来访问同步插件程序1607。
图16也示出了异步插件程序的集合。这些异步插件程序包括同步插件程序1612和手势识别器1609。异步插件程序1612是在被管理的空间中附加到RealTimeStylus部件1605的异步插入程序集合中的第一个异步插件程序。由于异步插件程序1612在被管理的空间中,因此,异步插入程序包装1619可以被用来允许从未被管理的RealTimeStylus部件1602那里对它进行访问。该手势识别器存在于被管理的空间和未被管理的空间中。具有其高速数据缓存1610的被管理的手势识别器1609是在异步插件程序1612之后被访问的下一个插件程序。手势识别器1609可以与该手势识别器(具有其高速数据缓存1614的1613)的未被管理的版本交换信息。
越过图16中的该被管理方与未被管理方之间的数据可能需要在未被管理的空间中所使用的这些结构与被管理的空间中所使用的结构之间加以转换或“整顿”。微软公司生产的.NET构架提供自动执行大部分的该整顿的互操作层。这个附加的数据处理招致隐含的性能代价,所以,如图16所示的设计被调整为将穿过互操作层的数量减到最少。
关于RTS 1605的被管理的包装与未被管理的RTS 1602之间的关系是与本地(未被管理的RTS 1602)的关系,该被管理的RTS 1605看起来象另一个RTS事件汇流点。当利用其构造器中的动态呈现器1615来加以例示时,RTS 1605访问对应的、未被管理的动态呈现器1608,并将它挂入在自身之后的同步插入程序集合。
被管理的手势识别器对象1609可能是异步插件程序的完全实施。它将数据包数据累积在该被管理方上,跨越该互操作层来对其进行整顿,并传入未被管理的代码实施1613。该返回码是:数据包是否对应于手势。
图16也示出被管理和未被管理的动态呈现器对象1615和1608。该被管理的动态呈现器对象可能是未被管理的动态呈现器1608的各个属性上的薄包装。被管理的动态呈现器1615是任选的。如果这里不例示动态呈现器1615,那么,可以将它例示为其他同步插件程序之一。
以下是用于创建图16中的系统的过程:
a.首先,开发者例示被管理的异步插件程序1612和被管理的动态呈现器1615。在内部,动态呈现器1615例示未被管理的动态呈现器1608,以便将属性设置往下传递。
b.其次,开发者在动态呈现器1615上设置属性(绘图属性等)。
c.第三,开发者例示实时针笔1602,处理该实时针笔构造器中的动态呈现器1615。可能会在内部发生一些事:
i.被管理的实时针笔1605询问(经由公共密封存取器)未被管理的动态呈现器1608的地址。
ii.被管理的实时针笔例示本地实时针笔1602,它将自身挂到笔服务1601。
iii.被管理的实时针笔1605将自身挂到作为实时针笔事件汇流点的该本地实时针笔1602。
iv.被管理的实时针笔1605将本地动态呈现器1608挂到其同步输出。
v.被管理的实时针笔1605将自身挂到本地实时针笔1602同步插入程序线程。
d.第四,开发者例示一个或多个被管理的同步和/或异步插入程序对象——可选地包括被管理的手势识别器1609。
e.第五,开发者将这些被管理的插入程序对象一起集合到各种插入程序集合中。(通过向这些RealTimeStylus部件通知应该访问这些插件程序的顺序,可以执行这一点。另外,为了将这些插件程序链栓在一起,可以根据第一个插件程序来设置属性)。
f.第六,开发者将被管理的异步插入程序对象1612与被管理的实时针笔1605 InkCollectionObject属性联系起来(从而将异步插入程序对象1612挂到该异步插入程序集合)。
g.第七,开发者将RTS.Enabled设置为“真”。这也可能使被管理的实时针笔1605在本地实时针笔1602上将该IrealTimeStylus->Enabled设置为“真”。
h.第八,事件开始通过实时针笔1602而流入。
可以利用另选性的布置来实现步骤(c)。例如,该API可能在该RTS构造器上不具有任何插件程序特定调节。相反,该RTS构造器的各种超载指示:将如何使用该RTS本身(例如,附加到窗口或控件、与一个或多人数字转换器“鼠标”对“笔行为”、等等关联)。由于多次越过该互操作边界的数据的性能暗示,可以使用该DynamicRenderer参数。结果,可以在成为该插入程序集合或链中的第一个或最后一个同步插件程序的体系结构意义上使用DynamicRederer。
图16示出了一种将这些互用性交叉减到最少的体系结构的方法,并允许该DynamicRenderer在该插件程序的有序清单中的任何地方。
以下描述用于使用图16中的该系统的过程:
a.笔服务1601调用RTS 1602上的功能,从而传递被累积的数据到与RealTimeStylus部件1602关联的该同步插入程序集合中。在一些情况中,来自输入队列1603的数据也可以被传入该插入程序集合。
b.当新数据出现在输入队列1603中时(或者,当在它向笔服务1601揭露的接口上调用这个适当的方法时),本地RTS 1602执行以下动作:
i.将数据包从数字转换器空间变换为himetric(“墨水空间”);
ii.将该逆变换(himetric→数字转换器)嵌入该数据包数据;以及,
iii.通过在该同步插入程序集合接口(在此情况下是被管理的RTS)上对该数据调用这个适当的功能,可以将该被变换的数据包数据传入该插入程序集合的第一个同步插件程序。
c.被管理的RTS 1605执行以下动作:
i.创建这些适当的被管理的数据结构,以便用管理友好的方法来保持该数据;
ii.调用这些被集合、被管理的同步插件程序上的这个适当的功能;
iii.确保“每个插件程序处理该数据并返回到RealTimeStylus部件1605”,以便可以调用下一个插件程序;以及,
iv.如此这般,直到它调用手势识别器1609上的这个对应的功能(如果正在使用手势识别器1609)。
d.动态呈现器1615可以由RealTimeStylus 1605来调用。当动态呈现器1615结束呈现这些新的数据包时,它返回,未被管理的RTS 1602检测“是否修改过数据包数据”,并将该适当的数据放入该队列。如果有任何“非直接”用户数据项目要添加,那么,它现在添加它们。
e.然后,本地RTS 1602将该私人消息寄到该附加窗口;以及,
f.然后,本地RTS 1602观察输入队列1603,来看看是否增加过任何实时数据,并且,如果是,则再次调用该同步插入程序集合,从而传递该数据。如果没有添加过数据,那么,本地RTS 1602返回,从而允许笔服务1601继续进行并利用新的数字转换器数据来再次调用RTS 1602。
g.该私人消息被本地RTS 1602上的该子类过程看到,它从队列1603中检索该数据,并调用该附加的同步插入程序接口上的这个适当的功能。
h.在此情况下,被管理的RTS 1605已连接本身,并且被调用。然后,被管理的RTS 1605调用异步插件程序1612上的这个对应的功能。这可以通过异步插入程序包装1619来加以传递。
i.然后,被管理的异步插件程序1612异步地处理该数据,从而适当地进行呈现或累积。
j.手势识别器1609可以作为离开该RealTimeStylus部件的该异步插入程序集合的一部分来加以调用。手势识别器1609在内部累积数据包,直到遇到CursorUp——那时,跨越该互操作性边界来将这些被累积的数据包传入用于识别的本地手势识别器1613。
i.这项操作返回关于“识别过哪个(哪些)手势”、以及“有多少笔划对应于这些可能的手势中的每个手势”的信息;
ii.然后,手势识别器1609使用被管理的RTS 1605(“立即”被设置为假)上的AddUserDataToQueue方法,以便将该手势识别的这些结果放入队列1604,用于异步消费。(这使该新的手势数据立即越过该互操作性边界(或互操作性)并参加另一个队列,直到该本地插入程序集合完成);以及,
iii.它另外向任何收听者激发传统的被管理事件,以便实时地向世界通知:刚刚发生过手势。
iv.然后,该当前数据为该插入程序集合中的任何附加的插件程序而被手势识别器1609返回到RealTimeStylus部件1605。
数据集和数据流
以下列出事件汇流点处理程序、以及与它们关联的信息:
·Source IrealTimePen 这个向后指针为该事件汇流点实施提供对该
来源RealTimeStylus的向后参考。这个指针
允许两件事:(a)访问关于该针笔实例的上下
文信息(例如,动态呈现器1615需要能够执
行数字转换器坐标与像素之间的单位换算),
以及(b)在多个RTS事件链之中被共享。
·TabletContextID 允许实时数据的该消费者有效率地累积数
据,并将该写字板ID用作该数据集合中的
索引器
·PacketDescription 描述数据包调用中的该数据布局。不同的数
字转换器支持不同的信息量——包括(例
如)x、y、压力、角度。该PacketDescription
向数据包的该接收者指出:该数据如何被安
排在最后到达的该平面整数阵列中。
·CursorID 允许实时数据的该消费者有效率地累积数
据,并将该光标ID用作关于该数据集合的
索引器。
·StylusInfo 联合方便信息的简单结构包括:
TabletContextID;
CursorID;
反向状态(这是指出相关性以及“该光标是对
应于笔的‘擦除器’端、还是‘书写’端”
的三态);
按钮状态(是否按压多达32个按钮中的每个
按钮);以及,
所需要的其他有关的信息。
·PropertyCountPerPacket 妥协参数,它允许开发者推断出该数据包数
据布局,而无须进行API调用。(X,Y被保
证是第一个并按照那个顺序,并且,计数允
许只对xy数据感兴趣的开发者经过跳过每
第n个元件的该清单。
·CountOfPackets 为效率起见而被“捆在一起”的数据包的
数量(笔服务和/或该数字转换器设备驱动器
确定:何时和有多少数据包用这个方法来捆
绑)。
·PacketData 这是该数据包数据的只读拷贝。
·CountOfPacketsRef 该被修改的数据包数据集中,开发者可以分
配给插件程序的数据包的数量。
·PacketDataRef 这是对该数据包数据的参考,它为插入程序
对象的开发者提供“修改该数据包数据”的
能力,以便实现涉及实时数据操作的情形。
在一项实施中,可能不允许插入程序集合实施“知道”:在进入该插入程序集合之前,是否已修改数据包数据。另外,这些插入程序集合可以被通知:是否已修改该数据包数据。例如,可以设置关于该数据的标志或独立于该数据的标志。“允许插入程序集合知道‘是否已修改数据包数据’”的一个优点为插入程序集合提供“谨慎地忽视被修改的数据包数据”的能力。另一方面,这个途径提供了供开发者犯错的进一步的选项。更重要的是,它混淆该设计样式的简单性和面向对象的性质,因为插件程序对于该数据的起源而言不再是不可知的了。如果该插件程序既可以检查原始数据、又可以检查被修改的数据,那么,它可能正在执行应属于前一个插件程序的操作。
由于性能/效率原因,可以在内部保持两个数据结构,使得除非该开发者意在修改该数据,否则,不需要分配该存储器。
数据同步
以下描述:数据如何可以被加入队列,以确保如图17A中所示的同步。
ICO可以将该输入和输出队列用作发信号机制,以便使在该UI线程上进入的其他请求与通过该墨迹作图线程来的挂起数据同步。
图17A示出了当该系统正在处理信息时发生的模式转换。该系统在1701处示出第一处理的结束(“完成”)。在时间1702处,新的针笔数据被接收,并开始在时间1702处由插件程序1来处理,在时间1704处由插件程序2来处理,并且在时间1705处结束。在时间1703处发生模式转换。例如,如果应用程序的该用户正将该“编辑模式”从“墨水”改成“编辑”,并且,该应用程序忙碌,那么,有一种合理的可能性:从该队列流出的数据包数据在该用户模式更改之后的某段时间内仍然是“墨水”。
但是,不是目前将该模式转换事件加入队列1706而是一直延迟到在时间1705处结束关于针笔数据的该当前处理为止。这可以按两种方法发生。首先,可以延迟该模式转换操作事件,直到在时间1702处始于这些插件程序中的该针笔数据完成。其次,该系统可以将该模式转换事件放入队列1706中,从而为在将要在该队列1706中被置于它前面的在时间1705处为来自插件程序2的该结果留出足够的空间。所以,在此情况下,该ICO可以在该用户作出该模式更改的那个时刻,将“标记符”插入该输出队列。在一段时间过去之后,那个标记符将被传回到该ICO中(经由实时针笔插入程序集合接口上的该CustomDataAdded方法),此时,该ICO可以开始将引入的数据包数据解释为“擦除器”请求。
图17B示出了图17A中的类属版本。关于第一个线程的过程的末端由事件1707来示出。它被放入队列1712。接下来,在时间1708处,在第一个线程上开始另一个过程。在时间1709处,在第二个线程上发生一个事件。由于第一个线程上的过程在时刻1708处开始,因此,预期在时间1709处的该事件之前执行那个过程。但是,由于第一个线程上的过程在时间1710处继续进行,然后在时间1711处结束,因此,将时间1709处的事件的插入定时为该过程的开始时间1708将会是不利的,这是因为:在该过程于时间1711处完成之前,时间1709处的该事件将会被放入该队列。这里,图17B示出了时间1711处的该事件,通过至少跳过队列1712中的一个地方,该事件被插入队列1712,它与从过程完成时刻1707中生成的那个事件有一段下游距离。通过在队列1712中保持一个地方可用,可允许过程的完成1708、1710、1711被适当地放入队列1712——在1709的该事件前面的位置,以允许按预期的顺序来读取队列1712中的这些数据包/事件。这里,该顺序可以被总结为:按其过程开始或事件发生的那个顺序来发生的数据包/事件。这个排序继续用于由时刻1713(过程开始)、1714(过程继续)和1715(过程完成)来示出的下一个过程。
图18和19示出了根据本发明的各个方面的用于处理笔数据的各种系统。
参考图18,笔设备1801将数据发送到笔服务1803。鼠标1802也可以生成信息,并将它发送到user32(也被称作“user32.dll”)1804。一些笔数据(例如,点击按钮)可以表示鼠标事件,并被改道发送到user32 1804,以便作为鼠标事件来加以处理。同样,一些鼠标事件可以表示墨水,并在1814处被改道发送,以便作为笔输入来加以处理。然后,鼠标事件被传递到窗口消息泵1805,再被传递到HWND 1806、HWND鼠标设备1812、输入队列1810,随后被传递到输入管理器1811。笔输入(例如,当该笔移入潜在的墨迹作图服务的范围时)或针笔事件被发送到笔输入管理器1807/1808(未被管理和被管理的实时针笔服务)。笔输入管理器1807/1808处理笔服务1803与应用程序之间的所有通信。可以在正常优先级线程上或在高优先级状态线程上执行这个处理。笔服务1803可以生成各种事件。笔事件可以被发送到笔输入管理器1807/1808,以绕过标准消息联系系统1804-1806和1812。
笔服务1803可以生成以下事件:范围内的针笔(其中,该针笔已进入该数字转换器的范围),范围外的针笔(其中,该针笔可以不再被该数字转换器检测到),针笔数据包(来自数字转换器的原始时刻数据——该笔可能会或可能不会接触该数字转换器),针笔在空中的点,写字板被增加/除去,以及系统手势事件(例如,“按压和保持”以及盘旋事件)。
该针笔可以生成原始预览事件。这些原始预览事件可以由实时墨迹作图服务1901(来自图19)来处理。其他服务也可以侦听这些事件。该实时墨迹作图服务1901可以对这些原始预览事件执行若干步骤——包括:
a.检验:事件是否是向下“数据包”事件。如果否,则停止处理并返回空。
b.根据其高速缓存的布局信息,来检验:事件是否将会已在墨迹作图元件上。如果否,则停止处理并返回空。
c.由于这个数据包在墨迹作图区内对“向下”事件,因此,递增地绘制该笔划。
d.最后,将在其上绘制过该笔划的那个元件返回到笔输入管理器1807/1808。
来自该原始预览事件的该返回值被笔输入管理器1807/1808用来“瞄准”该事件。如果非空目标被返回,那么,该事件可以被放在具有那个特殊目标的输入队列上。这确保:已被绘制在元件上的墨水实际上被传递到那个元件,而不是某个其他的元件——作为该输入队列中的其他事件的结果。
现在,该针笔事件准备好成为输入事件。但是,在大多数情况下,每个针笔事件也具有流过消息系统的对应的鼠标消息。在笔输入管理器1807/1808可以将该针笔事件转换成输入事件之前,首先应该将该事件与该对应的鼠标消息匹配。如果必要的话,笔输入管理器1807/1808可以等候该鼠标消息到达。
一旦笔输入管理器1807/1808既具有该鼠标消息、又具有该针笔事件,它就将两者结合成该适当的输入报告,并将该报告放置在输入队列1810上。
图20示出了根据本发明的各个方面的队列。图20包括队列2001。为简单起见,该队列被示作圆圈。如该技术领域中已知,也可以使用该队列的各个选择性形式——包括线性队列和业内众知的其他版本。队列2001包括开始指针2002和结束指针2008。队列2001也包括具有信息的若干位置(2003、2004和2009)。位置2005和2007是空的。位置2006已被锁定。位置2006可能已被锁定为位置持有符,以便使来自不同来源的事件和数据同步(图17A和17B中示出它们的例子)。当被包含在其内的该数据正通过插入程序集合或链栓来加以传递时,也可以锁定位置2006。位置2010和2011也是空的。可以按需要来增加或减少空白空间的数量。例如,如果该队列是满的,那么,可以增加附加的空间,以存储附加的数据。另外,该队列的尺寸可能是固定的,以便放弃多于在该队列中可以被保持的任何数据。这可以为该用户提供有用的好处,因为:它为该用户提供指示:该系统高度涉及其他过程,并且,它将会有助于减慢关于该队列的新数据的创建。该信息放弃也可以向该用户示出:该系统已被锁住,并且,在该系统又继续进行处理之前,还建议输入附加的数据。
应用编程接口
以下提供可以被本发明的各个方面使用的各种应用编程接口的纵览。
该实时针笔可以是实时针笔输入类别的一部分。该被例示的实时针笔对象可以附加到窗口处理或控件。该实时针笔可以包括默认构造器。通过使用默认构造器,可许可只从另一个实时针笔对象接受输入。
为了允许插件程序与笔数据流交互,该实时针笔对象可以保持两个插入程序集合。可以在该实时针笔对象的属性中规定这些集合(例如,关于同步插件程序的SyncPluginCollection和关于异步插件程序的AsyncPluginCollection)。通过在该适当的属性上调用增加方法(例如,用于将插件程序加入该同步集合的StylusSyncPluginCollection.Add、或用于将插件程序加入该异步集合的StyluAsyncPluginCollection.Add),可以将插件程序加入任何一个集合。
同步插件程序可以实现接口(例如,IStylusSyncPlugin),异步插件程序可以执行不同的接口(例如,IStylusAsyncPlugin)。每个插件程序可以具有规定其数据兴趣(例如,IStylusSyncPlugin.DataInterest或IStylusAsyncPlugin.DataInterest)的属性。该实时针笔对象可以调用该插件程序已用来预订的方法的该插件程序的通知方法。
该实时针笔对象执行该IStylusAsyncPlugin接口。例示从另一个实时针笔接受输入的实时针笔可以包括:使用默认构造器。可以使用更多另选机制来将子辈或串联的RTS与父辈联系起来。另一个机制可以使用与父RTS关联的专用指针来保持对该子RTS的参考。这里,该父RTS将不需要实现该异步插件程序接口。
该实时针笔对象可以具有传送笔数据的两个或更多的内部队列。这些包括该输入队列和该输出队列。可以在这两个队列之间增加另一个队列。此外,当数据只意在从笔数据流进入这些同步插件程序时,可以消除该输入队列。以上至少根据图6、8、11和13来描述这些队列用来处理笔数据的过程。
以下是用于在集合墨水的形式上使用该实时针笔对象的范例情形。
a.创建实现该IStylusAsyncPlugin接口的表单。
b.在该表单上创建附于控件的实时针笔对象。
c.将该表单设置成对通知感兴趣(所以对其进行接收),这些通知涉及针笔接触表面(StylusDown事件)、数据包、以及针笔向上(例如,StylusUp事件),表单属性中的通知关系到它感兴趣的数据(如DataZaterestProperts)。
d.在该表单的IStylusAsyncPlugin.StylusDown、IStylusAsyncPlugin.Packets和IStylusAsyncPlugin.StylusUp方法中,增加代码,来处理从该表单的实时针笔对象那里被发送的针笔向下、数据包和针笔向上通知。
每个实时针笔对象保持关于可以与它相互作用的这些对象的唯一标识符清单。该实时针笔对象可以具有用于在唯一标识符与写字板对象之间转变的一些方法。这些可以包括GetTabletContextIDFromTablet和GetTabletFromTabletContextID方法。
该笔数据可以占据其自已的名字空间(例如,StylusInput.PluginData名字空间)。
写字板属性说明对象(例如,TabletPropertyDescription对象)可以包含:属性全球唯一标识符(GUID),以及描述关于特殊写字板的该属性的范围、分辨率和单位的写字板属性质量(例如,TabletPropertyMetrics)结构。
可能存在一种方法——它采用唯一写字板标识符,并返回该写字板所支持的属性说明对象的集合。例如,该实时针笔对象的GetTabletPropertyDescriptionCollection方法采用唯一写字板标识符,并返回该写字板所支持的TabletPropertyDescription对象的该集合。该实时针笔对象的GetDesiredPacketDescription方法返回关于这些数据包属性的GUID阵列,该实时针笔对象将把这些数据包属性转发到其插件程序。
被发送到关于给定写字板的这些插件程序的这个数据包属性集可能是由GetTabletPropertyDescriptionCollection方法所返回的集合与由GetDesiredPacketDescription方法所返回的集合的交集。为了修改该实时针笔将传递到其插件程序的这个数据包属性集,可以调用该实时针笔对象的SetDesiredPacket Description方法。
当启用该实时针笔对象时,每个插件程序接收对其IStylusSyncPlugin.RealTimeStylusEnabled或IStylusAsyncPlugin.RealTimeStylusEnabled方法的调用。当启用该RealTimeStylus对象时,在该通知中被传递的RealTimeStylusEnabledData对象包含关于这些可用写字板的各个上下文标识符的集合。如果在启用该RealTimeStylus对象的时候,当RealTimeStylus对象所使用的写字板从启用笔的计算系统中添加或去除时,那么,该RealTimeStylus对象通知其插件程序:写字板已被增加或除去。
针笔可能具有附加的接口。每个针笔可以具有与其关联的信息,该信息描述与这些针笔关联的数据包。该实时针笔对象可以用许多通知方法来将关于这些针笔的信息传递到这些插件程序。关于笔或针笔的信息可以由针笔对象来表示。当搜集该数据时,该对象是该写字板笔的状态的快照。由于插件程序正在接收作为该写字板笔数据流的一部分的写字板笔数据,因此,这些插件程序应该使用该针笔对象中的该信息,而不是通过光标类别来检验特定写字板笔的当前状态。
以下描述插件程序和RealTimeStylus类别。插件程序——执行该IStylusSyncPlugin或IStylusAsyncPlugin接口的对象——可以被加入实时针笔对象。
IStylusSyncPlugin和IStylusAsyncPlugin接口定义相同的方法。这些方法允许实时针笔对象将笔数据传递到每个插件程序。该IStylusSyncPlugin.DataInterest和IStylusAsyncPlugin.DataInterest属性允许每个插件程序预订该写字板笔数据流中的特殊数据。插件程序应该只预订对于执行其任务而言是必要的该数据,这会将潜在的性能事项减到最少。另外,可以为插件程序而包括附加的预订。
该实时针笔对象可以在StylusInput.PluginData名字空间中使用对象,以便将该笔数据传递到其插件程序。该实时针笔也捕获插件程序所抛出的例外。当它这样做时,它可以通过调用该IStylusSyncPlugin.Error或IStylusAsyncPlugin.Error方法来通知这些插件程序。
以下描述插件程序数据和该实时针笔类别。
关于该实时针笔的插件程序可以执行该IStylusSyncPlugin接口或该IStylusAsyncPlugin接口。可能会或可能不会在该实时针笔中执行所有方法。
这些接口上所定义的各个方法可以在StylusInput.PluginData名字空间中使用对象,以便将该笔数据传递到这些插件程序。以下表格描述作为这些通知方法中的参数的各个数据对象,并列出与该通知关联的该DataInterestMask值。
插入式数据 |
DataInterestMask值 |
说明 |
CustomStylusData |
CustomStylusDataAdded |
被插件程序增加的自定义应用数据 |
ErrorData |
Error |
该实时针笔对象响应于其插件程序之一中的未经处理过的例外来增加的错误信息 |
InAirPacketsData |
InAirPackets |
当该针笔在该数字转换器之上的空中时,关于针笔运动的数据包信息 |
InAirPacketsData |
Packets |
当该针笔正接触该数字转换器时,关于针笔运动的数据包信息 |
RealTimeStylusDisabledData |
RealTimeStylusDisabled |
当它正被禁止时,该实时针笔对象增加的信息 |
RealTimeStylusEnabledData |
RealTimeStylusEnabled |
当它正被启用时,该实时针笔对象增加的信息 |
StylusButtonDownData |
StylusButtonDown |
关于正被压下的该特定针笔按钮的信息 |
StylusButtonUpData |
StylusButtonUp |
关于正被释放的该特定针笔按钮的信息 |
StylusDownData |
StylusDown |
当使针笔接触该数字转换器时,关于该针笔的数据包信息 |
StylusInRangeData |
StylusInRange |
关于正进入该实时针笔对象的输入区或正进入该实时针笔对象的该输入区之上的数字转换器的检测范围的特定针笔的信息 |
StylusOutOfRangeData |
StylusOutOfRange |
关于正离开该实时针笔对象的该输入区或正离开该实时针笔禁止数据对象的该输入区之上的该数字转换器的该检测范围的该特定针笔的信息 |
StylusUpData |
StylusUp |
当从该数字转换器那里提起针笔时,关于该针笔的数据包信息 |
SystemGestureData |
SystemGesture |
当它检测到系统手势时,该RealTimeStylus对象增加的信息 |
TabletAddedData |
TabletAdded |
关于正被增加的该写字 |
| |
板的信息 |
TabletRemovedData |
TabletRemoved |
关于正被除去的该写字板的信息 |
实时针笔对象用若干通知方法来将关于该写字板笔的信息传递到其插件程序。关于该写字板笔的信息由“针笔”对象来表示。当搜集该数据时,这个对象是该写字板笔的该状态的快照。由于插件程序正在接收作为该写字板笔数据流的一部分的该写字板笔数据,因此,这些插件程序应该使用该针笔对象中的该信息,而不是通过该“光标”类别来核对特定写字板笔的该当前状态。每个“针笔”对象包含关于搜集过该数据的该写字板的该写字板上下文标识符。
以下的13项功能可以在这些同步和异步接口上加以实现。该表格比较通过这各种事件来加以传递的该信息。该事件和参数清单起说明的作用,而不是包括所有的。其他事件和参数可以被用于以下内容或代替以下内容。
这些同步参数中的许多同步参数与这些异步参数的不同之处只在于:前者允许接收方修改通过该队列的该数据。另外,可以允许两个参数集修改通过这些队列的数据。
功能 |
目的 |
同步参数说明 |
异步参数说明 |
ContextCreate(a.k.a.RTSEnabled) |
被用来确定“何时已创建该写字板上下文”,以便可以启用事件链。这个事件的消费者可以使用这一点来知道RTS何时完成写字板初始化,并准备开始向客户代码激发数据 |
包括该笔的来源(包括(但不局限于)笔ID)、该写字板标识、以及这些数据包的说明 |
包括该笔的来源(包括(但不局限于)笔ID)、该写字板标识、以及这些数据包的说明 |
ContextDestroy(a.k.a.RTSDisabled) |
被用来确定“何时已破坏该写字板上下文”,以便RTS |
包括该笔的来源(包括(但不局限于)笔ID)和该写字板 |
包括该笔的来源(包括(但不局限于)笔ID)和该写字板 |
|
可以清除其对象。这个事件的消费者可以使用这一点来知道RTS何时将要释放写字板上下文(也许因为RTS.Enabled 是假),并在它不再可用之前按需要高速缓存任何PacketDescription数据 |
标识 |
标识 |
CursorNew |
通知:该数字转换器已遇到新的针笔 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等) |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等) |
CursorInRange |
通知:针笔已移入该数字转换器的范围 |
包括该笔的该来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等) |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等) |
CursorOutOfRange |
通知:针笔已移出该数字转换器的范围 |
包括笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激 |
| |
的该针笔上的按钮、等等) |
活的该针笔上的按钮、等等) |
CursorDown |
通知:针笔尖端正在“接触”该数字转换器表面 |
SourceRealTimePen,StylusInfo,PropertyCountPerPacket,PacketDataRef |
SourceRealTimePen,StylusInfo,PropertyCountPerPacket,PacketData |
CursorUp |
通知:针笔尖端不再接触该数字转换器表面 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等)。这也可以包括每一数据包的该属性计数、以及对该数据包数据类型的参考。 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等)。这也可以包括每一数据包的该属性计数、以及对该数据包数据类型的参考。 |
InAirPackets |
在数字转换器表面之上的针笔运动的通知 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的针笔上的按钮、等等)。这也可以包括每一数据包的属性计数、以及对该数据包数据类型的参考。这也可以包括数据包缓冲 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的针笔上的按钮、等等)。这也可以包括每一数据包的该属性计数、以及对数据包数据类型的参考。这也可以包括数据包缓冲 |
| |
长度和这些数据包的该计数。 |
长度和这些数据包的该计数。 |
Packets |
当接触该数字转换器表面时的针笔运动的通知 |
包括该笔的该来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等)。这也可以包括每一数据包的该属性计数、以及对该数据包数据类型的参考。这也可以包括数据包缓冲长度和这些数据包的该计数。 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的该针笔上的按钮、等等)。这也可以包括每一数据包的该属性计数、以及对该数据包数据类型的参考。这也可以包括数据包缓冲长度和这些数据包的该计数。 |
SystemEvent |
系统事件或手势的通知。例子包括“轻敲”、“双轻敲”、“按压和保持”、“摇动” |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的针笔上的按钮、等等)。这也可以包括涉及该系统事件的系统事件信息和数据。 |
包括该笔的该来源(包括(但不局限于)笔ID)和涉及该针笔的信息(包括(但不局限于)已被激活的针笔上的按钮、等等)。这也可以包括涉及该系统事件的系统事件信息和数据。 |
TabletAdded |
被连接到该系统(通常是外部USB设备)的新数字转换器的通知 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该写字板的信息 |
包括该笔的来源(包括(但不局限于)笔ID)和涉及该写字板的信息 |
TabletRemoved |
与该系统(通常是 |
包括该笔的来源 |
包括该笔的来源 |
|
外部USB设备)断开的数字转换器的通知 |
(包括(但不局限于)笔ID)和涉及被除去的写字板的信息 |
(包括(但不局限于)笔ID)和涉及被除去的该写字板的信息 |
UserData |
任意的用户数据——被独特地识别(例如,通过GUID)。这一点被专门的插件程序来使用,该专门的插件程序想要通过队列来将信息顺流传递到该“墨水集合对象”,并保证:它根据上述实时数据的其余部分来按正确的顺序进入。 |
n/a |
包括该笔的来源(包括(但不局限于)笔ID)、与该用户的数据相关联的GUID、该用户的数据的尺寸的指示、以及该用户的数据的内容 |
已借助说明性实施例来描述本发明的各个方面。通过回顾本揭示说明,掌握该技术领域的普通技能的人将会想到所附权利要求书的范围和精神以内的众多其他的实施例、修改和变更。