主要内容:

1.指针事件

2.操作事件

1.指针事件

指针事件由各种活动输入源引发,包括触摸、触摸板、笔和鼠标(它们替代传统的鼠标事件)。指针事件基于单一输入点(手指、笔尖、鼠标光标),但不支持基于速度的交互。下面是指针事件列表及其相关的事件参数列表:

事件或类 描述
PointerPressed 单根手指触摸屏幕时发生。
PointerReleased 该同一触摸接触抬起时发生。
PointerMoved 在屏幕上拖动指针时发生。
PointerEntered 在指针进入元素的点击测试区时发生。
PointerExited 在指针退出元素的点击测试区时发生。
PointerCanceled 异常丢失触摸接触时发生。
PointerCaptureLost 当另一个元素捕获指针时发生。
PointerWheelChanged 当鼠标滚轮的增量值更改时发生。
PointerRoutedEventArgs 为所有指针事件提供数据。

这些事件都是基于UI共同基类UIElement类的事件,对于大多数的UI元素都是适用的,利用上表中的前5个事件就基本可以实现单指操作的各种场景。一般用得最多的是PointerEntered和PointerExited两个事件。使用时,我们既可以在XAML里面注册这些事件,也可以在构造函数里面进行注册。

           

然后我们在这些事件里通过Debug.WriteLine("触发PointerXXX事件");打印出如下调试信息:

可以发现依次触发的事件是PointerEntered、PointerPressed、PointerMoved、PointerReleased、PointerExisted,手指只要在屏幕上稍微滑动一下,就有很多很多的PointerMoved事件被触发。。。

我们来看实例:

通过在圆上滑动来控制方块在一个区域的移动。

XAML:在这里使用的布局容器是Canvas,便于后面方块位置的控制。

   <StackPanel x:Name="TitlePanel" Grid.Row="0" Margin="12,24,0,28">
<TextBlock x:Name="ApplicationTitle" Text="鼠标事件" FontSize="20"/>
<Ellipse Height="100" Width="100" Fill="Red" Name="ellipse1" />
</StackPanel>
<Canvas x:Name="canvas" Background="DimGray" Height="400" Width="320" Grid.Row="1">
<Rectangle x:Name="rect" Fill="BurlyWood" Canvas.Left="140" Canvas.Top="180" Height="40" Width="40"></Rectangle>
</Canvas>

C#代码:判断是点击操作还是滑动操作,以及左滑右滑等是固定模式的代码,能理解就理解,不用刻意琢磨。还需注意如何获取控件在Canvas里的位置以及把方块限定在一个区域内。

    private void ellipse1_PointerExited(object sender, PointerRoutedEventArgs e)
{
Debug.WriteLine("触发PointerExited事件");
Point end = e.GetCurrentPoint(ellipse1).Position;
double angle = ;
double verticalDistance = (double)rect.GetValue(Canvas.TopProperty);
double horizontalDistance = (double)rect.GetValue(Canvas.LeftProperty); if (Math.Abs(end.X - start.X) < && Math.Abs(end.Y - start.Y) < )
{
angle = ;
}
else if (end.X > start.X)
{
if (end.Y > start.Y)
{
angle = - Math.Atan((end.Y - start.Y) * 1.0 / (end.X - start.X)) * / Math.PI;
}
else
{
angle = Math.Atan((start.Y - end.Y) * 1.0 / (end.X - start.X)) * / Math.PI;
}
}
else if (end.X < start.X)
{
if (end.Y > start.Y)
{
angle = Math.Atan((end.Y - start.Y) * 1.0 / (start.X - end.X)) * / Math.PI + ;
}
else
{
angle = - Math.Atan((start.Y - end.Y) * 1.0 / (start.X - end.X)) * / Math.PI;
}
}
if (angle == )
{
//点击操作
}
else if (angle >= && angle < )
{
// 滑动操作:从下往上
if (verticalDistance >)
Canvas.SetTop(rect, (double)rect.GetValue(Canvas.TopProperty)-);
}
else if (angle <= || angle > )
{
// 滑动操作:从左向右滑
if (horizontalDistance < canvas.Width-)
Canvas.SetLeft(rect, (double)rect.GetValue(Canvas.LeftProperty) + );
}
else if (angle >= && angle < )
{
//滑动操作:从右向左滑
if (horizontalDistance >)
Canvas.SetLeft(rect, (double)rect.GetValue(Canvas.LeftProperty) - );
}
else if (angle >= && angle < )
{
//滑动操作:从上往下
if (verticalDistance <canvas.Height-)
Canvas.SetTop(rect, (double)rect.GetValue(Canvas.TopProperty) + );
}
}
private void ellipse1_PointerEntered(object sender, PointerRoutedEventArgs e)
{
start = e.GetCurrentPoint(ellipse1).Position;
}

来一个很小的预览图意思一下:

简单的实现一个涂鸦板

XAML:定义了一个Canvas、三个AppBarButton。

 <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Canvas Name="canvas"
Background="Transparent"
PointerEntered="canvas_PointerEntered"
PointerPressed="canvas_PointerPressed"
PointerMoved="canvas_PointerMoved"
PointerExited="canvas_PointerExited">
</Canvas>
</Grid> <Page.BottomAppBar>
<CommandBar IsOpen="False">
<CommandBar.PrimaryCommands>
<AppBarButton Icon="Back" Label="撤销" Click="AppBarButton_Click"></AppBarButton>
<AppBarButton Icon="FontColor" Label="颜色">
<AppBarButton.Flyout>
<Flyout x:Name="colorflyout">
<ListView x:Name="colorlv" IsItemClickEnabled="True" ItemClick="colorlv_ItemClick" >
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock FontSize="12" Text="{Binding}"></TextBlock>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
<AppBarButton Icon="FontSize" Label="字体">
<AppBarButton.Flyout>
<Flyout x:Name="fontflyout" >
<Slider x:Name="fontslider" Width="100" Minimum="2" Maximum="15" SmallChange="1"
Orientation="Horizontal" ValueChanged="Slider_ValueChanged" ></Slider>
</Flyout>
</AppBarButton.Flyout>
</AppBarButton>
</CommandBar.PrimaryCommands>
</CommandBar>
</Page.BottomAppBar>

C#代码:

下面这段代码主要用来画线,涉及到PointerPressed和PointerMoved事件。

 private void canvas_PointerPressed(object sender, PointerRoutedEventArgs e)
{
currentPoint = e.GetCurrentPoint(canvas).Position;
lastPoint = currentPoint;
} private void canvas_PointerMoved(object sender, PointerRoutedEventArgs e)
{
currentPoint = e.GetCurrentPoint(canvas).Position; Line line = new Line() { X1 = currentPoint.X, Y1 = currentPoint.Y, X2 = lastPoint.X, Y2 = lastPoint.Y };
line.Stroke = new SolidColorBrush(color);
line.StrokeThickness = fontsize;
line.StrokeLineJoin = PenLineJoin.Round;
line.StrokeStartLineCap = PenLineCap.Round;
line.StrokeEndLineCap = PenLineCap.Round;
this.canvas.Children.Add(line);
lastPoint = currentPoint;
lineCount++;
}

接着,我们考虑一下,该如何删除最后画在屏幕上的那条线呢?你可能会想到这句代码this.canvas.Children.RemoveAt(this.canvas.Children.Count - 1);(如果用这句代码,你可能要点很多下撤销按钮才能删除最后那条线),然而我们从上面可以知道,只要手指有滑动,就会不断触发PointerMoved事件,每次触发这个事件都会画一条线,只是那些线都首尾相接了,所以我们最后画在屏幕上的那条线其实是一系列的线首尾相接而成。具体的删除方法,请看下面的代码:

 private void canvas_PointerEntered(object sender, PointerRoutedEventArgs e)
{
lineCount = ;
}
private void canvas_PointerExited(object sender, PointerRoutedEventArgs e)
{
lineCountList.Add(lineCount);
}
private void AppBarButton_Click(object sender, RoutedEventArgs e)
{
if (lineCountList.Count > )
{
int lines = lineCountList[lineCountList.Count - ];
for (int i = ; i < lines; i++)
{
this.canvas.Children.RemoveAt(this.canvas.Children.Count - );
}
lineCountList.RemoveAt(lineCountList.Count - );
}
}

lineCount是定义在MainPage类中的变量(用来记录在PointerMoved中画的线的条数,也就是我们最近在屏幕上画的那条线实际包含线的条数),我们在PointerEntered给lineCount赋初值0,然后在PointerMoved里面执行加1操作,最后在PointerExited事件中将lineCount添加到集合lineCountList中进行保存,然后在AppBarButton_Click中进行具体的删除。至于一下删除所有,那就直接 canvas.Children.Clear();

颜色设置和字号设置的代码很简单就不贴了,下面来看图吧。我们这个示例最好在手机上调试,PC的话,只要鼠标在应用程序的区域移动就会画线,有点烦人。

 

2.操作事件

如果需要在应用中支持多个手指或速度数据的交互,则要使用操作事件。我们还可以使用操作事件来检测拖动、缩放和按住之类的交互。下表是操作事件及其相关的事件参数。

事件或类 描述
ManipulationStarting event 首次创建操作处理器时发生。
ManipulationStarted event 当输入设备在 UIElement 上开始操作时发生。
ManipulationDelta event 当输入设备在操作期间更改位置时发生。
ManipulationInertiaStarting event 在操作过程中,当延迟开始时,如果输入设备与 UIElement 对象失去联系,则会发生。
ManipulationCompleted event UIElement 上的操作和延迟完成时发生。
ManipulationStartingRoutedEventArgs 提供 ManipulationStarting 事件的数据。
ManipulationStartedRoutedEventArgs 提供 ManipulationStarted 事件的数据。
ManipulationDeltaRoutedEventArgs 提供 ManipulationDelta 事件的数据。
ManipulationInertiaStartingRoutedEventArgs 提供 ManipulationInertiaStarting 事件的数据。
ManipulationVelocities 描述操作发生的速度。
ManipulationCompletedRoutedEventArgs 提供 ManipulationCompleted 事件的数据。

我们的手势事件是由一系列操作事件组成。每个手势都是从ManipulationStarted事件开始,当用户触摸屏幕时,将会触发一个或多个ManipulationDelta事件,当手势完成用户手指离开屏幕时,会触发ManipulationCompleted事件。ManipulationStarting事件则是Manipulation系列事件最开始触发的事件,ManipulationInertialStarting事件则是在ManipulationDelta事件触发的过程中,如果有延迟则会发生,并不是必然会触发的事件。如下图所示:

在这些事件中,最重要的一个事件就是ManipulationDelta事件,相关手势的逻辑判断都要依赖于这个事件,而在一次触控当中,这个事件又可能被触发多次,和上面提到的PointerMoved事件类似,所以处理起来还是比较麻烦的。ManipulationDelta事件通过参数ManipulationDeltaRoutedEventArgs对象来传递相关的触摸和滑动信息,我们可以转到定义看一下这个类它所提供的一些属性,主要关注ManipulationDelta类型的两个属性Cumulative和Delta,Cumulative记录自开始操作之后的全部更改,Delta则是当前操作的最近更改。ManipulationDelta类,我们也可以转到定义看一下, 有System.Single(单精度浮点类型)类型的三个参数:Expansion(触摸触点间的距离更改,以DIP表示)、Rotation(旋转角度的变化,以度为单位)、Scale(触摸触点间的距离更改,以百分比表示)和Point类型的Translation(表示平移距离)。

另外,我们在使用Manipulation系列事件的时候,还需要设置ManipulationMode属性,其值为ManipulationModes枚举,具体的枚举值我们可以转到定义进行查看。

(实例实例,,,,请看下回。。。。)

操作事件,尤其是ManipulationDelta事件用得还是比较多的,然后这一部分的内容也是有一定的难度,需要重点掌握一下。由于准备不足,这部分的内容下次再继续讨论咯。好了,晚安!

本次内容的Demo链接:http://pan.baidu.com/s/1jHaa2BO 密码:5btc

Windows 10开发基础——指针事件和操作事件(一)的更多相关文章

  1. Windows 10开发基础——文件、文件夹和库(一)

    原文:Windows 10开发基础--文件.文件夹和库(一) 主要内容: 1.枚举查询文件和文件夹 2.文本文件读写的三种方法——创建写入和读取文件 3.获得文件的属性 枚举查询文件和文件夹 先了解一 ...

  2. Windows 10开发基础——网络编程

    主要内容: HttpClient类 Socket通信 WCF通信 HttpClient类      在UWP中可以用来进行网络通信的HttpClient类有两个,System.Net.Http.Htt ...

  3. Windows 10开发基础——XML和JSON (二)

    主要内容: Linq to XML Newtonsoft.Json.Linq来解析JSON 博客园RSS(http://www.cnblogs.com/rss)的解析 UWP调用自己实现的Web AP ...

  4. Windows 10开发基础——XML和JSON (一)

    主要内容: JSON的序列化与反序列化 XML的序列化与反序列化 1.JSON的序列化与反序列化     JSON(JavaScript Object Notation)是一种轻量级的数据交换语言,它 ...

  5. Windows 10开发基础——VS2015 Update1新建UWP项目,XAML设计器无法加载的解决

    这次,我们来解决一个问题...在使用Visual Studio 2015 Update 1的时候,新建一个UWP的项目,XAML设计器就会崩,具体异常信息如下图: 解决方法如下:下面圈出的那个路径就按 ...

  6. Windows 10开发基础——文件、文件夹和库(二)

    主要内容: 使用选取器打开和保存文件 关于文件.文件夹和库,如果深究其实还是有比较多的内容,我们这一次来学习一下选取器就收了.还有上篇博文中读写文本文件的三种方式可以细细体会一下. 文件选取器包含文件 ...

  7. Windows 10开发基础——启动默认应用的URI

    主要内容:通过指定的URI来启动默认的应用(设置,应用商店,地图,人脉) 方法一:直接在XAML中添加如下代码 <TextBlock x:Name="LocationDisabledM ...

  8. Windows 10 开发人员预览版中的新增功能(转自 IT之家)

    Windows 10 开发人员预览版中的新增功能 在Win10预览版中安装工具与SDK后,即可着手创建Windows通用应用或先浏览目前的环境与此前相比都发生了什么变化. 应用建模 文件资源管理器: ...

  9. Windows驱动程序开发基础(四)驱动的编译调试和安装

    Windows驱动程序开发基础,转载标明出处:http://blog.csdn.net/ikerpeng/article/details/38793995 以下说一下开发出来驱动程序以后怎样编译.一般 ...

随机推荐

  1. 关于ulimit -a中需要修改的两个值

    以root用户运行 ulimit -a 命令,其中有两个参数分别为: open files和max user processes   修改方法:  vi /etc/security/limits.co ...

  2. Photoshop怎么实现图片局部马赛克

    学好ps是一件很重要的事情,作为日常必备技能,不管是在遇到这样的同时请求帮忙或者老板发配的任务的时候,就能分分钟派上用场了. 1:安装运行photoshop,点击文件-打开,选择要ps的图片. 图片. ...

  3. 【hdu5692】Snacks

    Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submissio ...

  4. [Angular] Create a custom pipe

    For example we want to create a pipe, to tranform byte to Mb. We using it in html like: <div> ...

  5. Thermally driven workload scheduling in a heterogeneous multi-processor system on a chip

    Various embodiments of methods and systems for thermally aware scheduling of workloads in a portable ...

  6. 【先进的算法】Lasvegas算法3SAT问题(C++实现代码)

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46469557 1.SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问 ...

  7. MATLAB Toolbox Path Cache is out of date and is not being used的解决

    作者:朱金灿 来源:http://blog.csdn.net/clever101 使用mcc编译MATLAB\R2009a\extern\examples\compiler目录下的hello.m,编译 ...

  8. 理解React生命周期的好例子

    class App extends React.Component { static propTypes = { }; static defaultProps = { }; constructor(p ...

  9. WPF 好看的矢量图标

    原文:WPF 好看的矢量图标 本文告诉大家一个好用的网站,里面提供很多好看的图标. 本文介绍的网站是 Xamalot 里面有很多好看的图标. 例如我找到了一个好看的图标 我只需要点击下面的下载就可以了 ...

  10. LoadFromStr的使用中出现错误“未结束的字符串常量”

    最近遇到个奇怪的问题,就是关于js参数中待换行符时,出现了错误“为结束的字符串常量”. 解决方法是:不直接将该数据以参数形式传递,而是先将其赋值在一个隐藏的文本内,需要调用的函数里只需读取该文本里的内 ...