WPF应用程序中输入系统介绍

来源:互联网 发布:阴上买入指标源码 编辑:程序博客网 时间:2024/05/20 17:23

      当开发一个WPF应用程序时,开发者并不需要特别关注用户输入机制。WPF会为我们处理这些机制使得我们可以关注于如何响应用户的输入。毕竟作为一个开发者,我们更应该关心如何对用户输入的信息进行分析处理,而不是重新造轮子来考虑如何去收集用户的输入。如果应用程序需要一个按钮,只需要从工具箱中拖一个按钮出来放在界面上,然后在按钮的点击事件中编写处理逻辑即可。在大多数情况下,开发者可能需要对按钮设置不同的外观以响应用户鼠标的不同状态。WPF会在底层上为我们实现这些事件,诸如鼠标何时悬停在按钮上,或者被点击。

    WPF有一个健全的输入系统来从输入设备中获取用户的输入信息,并响应这些输入信息所带来的控件变化。这些API位于System.Windows.Input命名空间中(Presentation.Core.dll),这些API直接从操作系统获取输入设备输入的数据,例如,名为Keyboard,Mouse,Stylus,Touch和Cursor的这些类。InputManager这个类负责管理所有输入设备获取的信息,并将这些信息传递到表现框架中。

    WPF的另一类组件是位于System.Windows命名空间(PresentationCore.dll)下面的四个类,他们是UIElement,ContentElement,FrameworkElement以及FrameworkContentElement 。FrameworkElement继承自UIElement,FrameworkContentElement继承自ContentElement。这几个类是WPF中所有可视化元素的基类,如Button,TextBlock及ListBox。更多WPF输入系统相关信息可以参考MSDN文档。

    InputManager监听所有的输入设备,并通过一系列方法和事件来通知UIElement和ContentElement对象,告知这些对象输入设备进行了一些有关可视化元素相关的操作。例如,在WPF中,当鼠标光标进入到可视化控件的有效区域时就会触发MouseEnterEvent事件。UIElement和ContentElement对象也有OnMouseEnter事件。这使得任何继承自UIElement或者ContentElement类的对象也能够接受来自输入设备的所触发的事件。WPF会在触发任何其它输入事件之前调用这些方法。在UIElement和ContentElement类中也有一些类似的事件包括MouseEnter,MouseLeave,MouseLeftButtonDown,MouseLeftButtonUp,TouchEnter,TouchLeave,TouchUp和TouchDown。

    有时候开发者需要直接访问鼠标或者其他输出设备,InputManager对象有一个称之为PrimaryMouseDevice的属性。他返回一个MouseDevice对象。使用MouseDevice对象,能够在任何时候通过调用GetScreenPositon来获取鼠标的位置。另外,MouseDevice有一个名为GetPositon的方法,可以传入一个UI界面元素,将会返回在该UI元素所在的坐标空间中的鼠标位置。当需要判断鼠标悬停等操作时,这些信息尤其重要。当Kinect SDK每一次产生一幅新的SkeletonFrame帧数据时,我们需要进行坐标空间转换,将关节点位置信息转换到UI空间中去,使得可视化元素能够直接使用这些数据。当开发者需要将鼠标作为输入设备时, MouseDevice对象中的GetScreenPositon和GetPosition方法能提供当前鼠标所在点的位置信息。

    在有些情况下,Kinect虽然和鼠标相似,但是某些方面差别很大。骨骼节点进入或者离开UI上的可视化元素这一点和鼠标移入移出行为类似。换句话说,关节点的悬停行为和鼠标光标一样。但是,类似鼠标点击和鼠标按钮的按下和弹起这些交互,关节点与UI的交互是没有。在后面的文章中,可以看到使用手可以模拟点击操作。在Kinect中相对于实现鼠标移入和移出操作来说,对鼠标点击这种支持相对来说较弱。

    Kinect和触摸板也没有太多相同的地方。触摸输入可以通过名为Touch或者TouchDevice的类来访问。单点的触摸输入和鼠标输入类似,然而,多点触控是和Kinect类似的。鼠标和UI之间只有一个交互点(光标)但是触摸设备可以有多个触控点。就像Kinect可以有多个游戏者一样。从每一个游戏者身上可以捕捉到20个关节点输入信息。Kinect能够提供的信息更多,因为我们知道每一个输入点是属于游戏者身体的那个部位。而触控输入设备,应用程序不知道有多少个用户正在触摸屏幕。如果一个程序接收到了10个输入点,无法判断这10个点是一个人的10个手指还是10个人的一个手指触发的。 虽然触控设备支持多点触控,但这仍然是一种类似鼠标或者手写板的二维的输入。然而,触控输入设备除了有X,Y点坐标外,还有触控接触面积这个字段。毕竟,用户用手指按在屏幕上没有鼠标光标那样精确,触控接触面积通常大于1个像素。

    当然,他们之间也有相似点。Kinect输入显然严格地符合WPF 所支持的任何输入设备的要求。除了有其它输入设备类似的输入方式外,他有独特的和用户进行交互的方式和图形用户界面。核心上,鼠标,触控板和手写板只传递一个像素点位置嘻嘻你。输入系统确定该点在可见元素上下文中的像素点位置,然后这些相关元素响应这个位置信息,然后进行响应操作。

    期望是在未来Kinect能够完整的整合进WPF。在WPF4.0中,触控设备作为一个单独的模块。最开始触控设备被作为微软的Surface引入。Surface SDK包括一系列的WPF控件,诸如SurfaceButton,SurfaceCheckBox,和SurfaceListBox。如果你想按钮能够响应触摸事件,最好使用SurfaceButton控件。

能够想象到,如果Kinect被完整的整合进WPF,可能会有一个称之为SkeletonDevice的类。他和Kinect SDK中的SkeletonFrame对象类似。每一个Skeleton对象会有一个称之为GetJointPoint的方法,他和MouseDevice的GetPositon和TouchDevice的GetTouchPoint类似。另外,核心的可视化元素(UElement, ContentElement, FrameworkElement, FrameworkContentElement) 有能够相应的事件或者方法能够通知并处理骨骼关节点交互。例如,可能有一个JointEnter,JointLeave,和JointHover事件。更进一步,就像触控类有一个ManipulationStarted和ManipulationEnded事件一样,在Kinect输入的时候可能伴随GetstureStarted和GestureEnded事件。

    目前,Kinect SDK和WPF是完全分开的,因此他和输入系统没有在底层进行整合。所以作为开发者的我们需要追踪骨骼关节点位置,并判断节点位置是否和UI界面上的元素有交互。当关节点在对应的UI坐标系可视化界面的有效范围内时,我们必须手动的改变这些可视化元素的外观以响应这种交互。