背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性

简介: 原文:背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性[源码下载] 背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manip...
原文: 背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性

[源码下载]


背水一战 Windows 10 (69) - 控件(控件基类): UIElement - Manipulate 手势处理, 路由事件的注册, 路由事件的冒泡, 命中测试的可见性



作者:webabcd


介绍
背水一战 Windows 10 之 控件(控件基类 - UIElement)

  • Manipulate 手势处理
  • 路由事件的注册
  • 路由事件的冒泡
  • 命中测试的可见



示例
1、演示 Manipulate 手势处理
Controls/BaseControl/UIElementDemo/ManipulateDemo.xaml

<Page
    x:Class="Windows10.Controls.BaseControl.UIElementDemo.ManipulateDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <Grid Margin="10 0 10 10">

            <TextBlock Name="lblMsg" Margin="5" />

            <Rectangle Name="rectangle" Height="200" Width="200" Fill="Orange" Margin="5" />

        </Grid>
    </Grid>
</Page>

Controls/BaseControl/UIElementDemo/ManipulateDemo.xaml.cs

/*
 * UIElement - UIElement(继承自 DependencyObject, 请参见 /Controls/BaseControl/DependencyObjectDemo/)
 *     ManipulationModes - 需要监测的手势(Windows.UI.Xaml.Input.ManipulationModes 枚举)
 *         None - 禁用手势监测
 *         TranslateX, TranslateY - 位移手势
 *         TranslateRailsX, TranslateRailsY - 带有轨道的位移手势
 *         Rotate - 旋转手势
 *         Scale - 缩放手势
 *         TranslateInertia - 带有惯性的位移手势
 *         RotateInertia - 带有惯性的旋转手势
 *         ScaleInertia - 带有惯性的缩放手势
 *         All - 监测全部手势
 *     ManipulationStarting - 触控操作开始时触发的事件
 *     ManipulationStarted - 触控操作开始后触发的事件
 *     ManipulationInertiaStarting - 触控操作的惯性开始时触发的事件
 *     ManipulationCompleted - 触控操作结束后触发的事件
 *     ManipulationDelta - 触控值发生变化时触发的事件
 * 
 * ManipulationStartingRoutedEventArgs
 *     Container - 此 Manipulation 的容器
 *     Mode - 获取或设置 ManipulationModes
 *     Pivot - 获取或设置轴对象,ManipulationPivot 类型的数据
 *         Center - 旋转中心点
 *         Radius - 有效的旋转半径
 * 
 * ManipulationStartedRoutedEventArgs
 *     Container - 此 Manipulation 的容器
 *     Cumulative - 自操作开始后的累计变化量,返回 ManipulationDelta 类型的对象
 *     Position - 触摸点相对于 UIElement 的位置
 *     Complete() - 马上完成 Manipulation 而不发生惯性
 * 
 * ManipulationDeltaRoutedEventArgs
 *     Container - 此 Manipulation 的容器
 *     Cumulative - 自操作开始后的累计变化量,返回 ManipulationDelta 类型的对象
 *     Delta - 当前变化量,返回 ManipulationDelta 类型的对象
 *     Velocities - 当前变化的速率,返回 ManipulationVelocities 类型的对象
 *     IsInertial - 是否在惯性运动之中
 *     Position - 触摸点相对于 UIElement 的位置
 *     Complete() - 马上完成 Manipulation 而不发生惯性
 *     
 * ManipulationInertiaStartingRoutedEventArgs
 *     Container - 此 Manipulation 的容器
 *     Cumulative - 自操作开始后的累计变化量,返回 ManipulationDelta 类型的对象
 *     Delta - 当前变化量,返回 ManipulationDelta 类型的对象
 *     Velocities - 当前变化的速率,返回 ManipulationVelocities 类型的对象
 *     ExpansionBehavior - 惯性的缩放行为,获取或设置 InertiaExpansionBehavior 类型的对象
 *         DesiredDeceleration - 惯性运动时,缩放的减慢速率
 *         DesiredExpansion - 惯性结束后,缩放的值
 *     RotationBehavior - 惯性的旋转行为,获取或设置 InertiaRotationBehavior 类型的对象
 *         DesiredDeceleration - 惯性运动时,旋转的减慢速率
 *         DesiredRotation - 惯性结束后,旋转的度数
 *     TranslationBehavior - 惯性的位移行为,获取或设置 InertiaTranslationBehavior 类型的对象
 *         DesiredDeceleration - 惯性运动时,直线位移的减慢速率
 *         DesiredDisplacement - 惯性结束后,直线位移的的值
 *         
 * ManipulationCompletedRoutedEventArgs
 *     Container - 此 Manipulation 的容器
 *     Cumulative - 自操作开始后的累计变化量,返回 ManipulationDelta 类型的对象
 *     Velocities - 当前变化的速率,返回 ManipulationVelocities 类型的对象
 *     IsInertial - 结束前是否发生了惯性运动
 *     Position - 触摸点相对于 UIElement 的位置
 * ManipulationDelta - 变化量
 *     Expansion - 触摸点间距离的变化,单位 dip
 *     Scale - 触摸点间距离的变化,以一个百分比表示
 *     Rotation - 旋转角度的变化,以角度为单位
 *     Translation - 位移的变化,Point 类型的对象
 * ManipulationVelocities - 变化速率
 *     Angular - 旋转速度,单位:度/毫秒
 *     Expansion - 缩放速度,单位:dip/毫秒
 *     Linear - 直线位移速度,单位:Point/毫秒
 *     
 * 
 * 什么是 dip: device independent pixels(设备独立像素),不管屏大小和分辨率,把屏幕分成 480 * 320 个点,其中每一点代表 1 dip
 * Manipulate 是 UIElement 级别的手势操作;GestureRecognizer 是 app 级别的手势识别
 * 
 * 
 * 本例用于演示 UIElement 的 Manipulate 的应用(位移手势,缩放手势,旋转手势)
 * 
 * 
 * 注:关于 Manipulate Pointer Tap 的区别如下
 * 1、Manipulate 是最底层,Pointer 在中间,Tap 是最高层,所以会先走 Manipulate 事件,再走 Pointer 事件,最后走 Tap 事件
 * 2、如果高层的事件被触发,最相对于它的底层的事件也会被触发,反之则不一定
 * 3、使用原则是能在高层处理的事件尽量在高层处理(开发会简单些)
 */

using System;
using Windows.Foundation;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;

namespace Windows10.Controls.BaseControl.UIElementDemo
{
    public sealed partial class ManipulateDemo : Page
    {
        private TransformGroup _transformGroup;
        private CompositeTransform _compositeTransform;
        private MatrixTransform _previousTransform;

        public ManipulateDemo()
        {
            this.InitializeComponent();

            // 监测全部手势
            rectangle.ManipulationMode = ManipulationModes.All;
            // 仅监测旋转手势和缩放手势
            // rectangle.ManipulationMode = ManipulationModes.Rotate | ManipulationModes.Scale;

            _transformGroup = new TransformGroup();
            _compositeTransform = new CompositeTransform();
            _previousTransform = new MatrixTransform() { Matrix = Matrix.Identity };

            _transformGroup.Children.Add(_previousTransform);
            _transformGroup.Children.Add(_compositeTransform);

            rectangle.RenderTransform = _transformGroup;

            rectangle.ManipulationStarting += rectangle_ManipulationStarting;
            rectangle.ManipulationStarted += rectangle_ManipulationStarted;
            rectangle.ManipulationInertiaStarting += rectangle_ManipulationInertiaStarting;
            rectangle.ManipulationCompleted += rectangle_ManipulationCompleted;
            rectangle.ManipulationDelta += rectangle_ManipulationDelta;
        }

        void rectangle_ManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e)
        {
            _previousTransform.Matrix = _transformGroup.Value;

            // 获取操作点相对于此 GeneralTransform 的位置
            Point center = _previousTransform.TransformPoint(new Point(e.Position.X, e.Position.Y));
            _compositeTransform.CenterX = center.X;
            _compositeTransform.CenterY = center.Y;

            _compositeTransform.Rotation = e.Delta.Rotation;
            _compositeTransform.ScaleX = e.Delta.Scale;
            _compositeTransform.ScaleY = e.Delta.Scale;
            _compositeTransform.TranslateX = e.Delta.Translation.X;
            _compositeTransform.TranslateY = e.Delta.Translation.Y;
        }

        void rectangle_ManipulationStarting(object sender, ManipulationStartingRoutedEventArgs e)
        {
            lblMsg.Text += "ManipulationStarting";
            lblMsg.Text += Environment.NewLine;
        }

        void rectangle_ManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e)
        {
            lblMsg.Text += "ManipulationStarted";
            lblMsg.Text += Environment.NewLine;
        }

        void rectangle_ManipulationInertiaStarting(object sender, ManipulationInertiaStartingRoutedEventArgs e)
        {
            lblMsg.Text += "ManipulationInertiaStarting";
            lblMsg.Text += Environment.NewLine;
        }

        void rectangle_ManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
        {
            lblMsg.Text += "ManipulationCompleted";
            lblMsg.Text += Environment.NewLine;
        }
    }
}


2、演示路由事件的注册, 路由事件的冒泡, 命中测试的可见性
Controls/BaseControl/UIElementDemo/EventDemo.xaml

<Page
    x:Class="Windows10.Controls.BaseControl.UIElementDemo.EventDemo"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:Windows10.Controls.BaseControl.UIElementDemo"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d">

    <Grid Background="Transparent">
        <StackPanel Margin="10 0 10 10">

            <Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="5">
                <!--
                    演示事件冒泡:儿子传递事件给爸爸,爸爸传递事件给爷爷,这就是事件冒泡
                -->
                <Border Name="borderRed" Background="Red" Width="300" Height="300">
                    <Border Name="borderGreen" Background="Green" Width="250" Height="250" Tapped="borderGreen_Tapped">
                        <Border Name="borderBlue" Background="Blue" Width="200" Height="200" Tapped="borderBlue_Tapped">
                            <Border Name="borderOrange" Background="Orange" Width="150" Height="150" Tapped="borderOrange_Tapped">
                                <!--通过 IsHitTestVisible="False" 设置命中测试不可见,也就是说 borderPurple 和 borderYellow 均命中测试不可见-->
                                <Border Name="borderPurple" Background="Purple" Width="100" Height="100" Tapped="borderPurple_Tapped" IsHitTestVisible="False">
                                    <Border Name="borderYellow" Background="Yellow" Width="50" Height="50" Tapped="borderYellow_Tapped" />
                                </Border>
                            </Border>
                        </Border>
                    </Border>
                </Border>

                <!--
                    像这样排列元素,是没有事件冒泡的,而只是前面的元素响应事件,后面的元素不会响应事件,也就是说同辈间没有事件冒泡的概念
                    IsHitTestVisible - 是否对命中测试可见(如果需要后面的元素响应事件,而前面的元素不响应事件,则只需要把前面的元素的命中测试设置为不可见即可)
                    <Rectangle Name="rectangle1" Width="200" Height="200" Fill="Red" />
                    <Rectangle Name="rectangle2" Width="200" Height="200" Fill="Green" />
                    <Rectangle Name="rectangle3" Width="200" Height="200" Fill="Blue" />
                    <Rectangle Name="rectangle4" Width="200" Height="200" Fill="Orange" />
                    <Rectangle Name="rectangle5" Width="200" Height="200" Fill="Purple" />
                -->
            </Grid>

            <TextBlock Name="lblMsg" Margin="5" />

        </StackPanel>
    </Grid>
</Page>

Controls/BaseControl/UIElementDemo/EventDemo.xaml.cs

/*
 * UIElement - UIElement(继承自 DependencyObject, 请参见 /Controls/BaseControl/DependencyObjectDemo/)
 *     IsHitTestVisible - 是否对命中测试可见
 *     AddHandler(RoutedEvent routedEvent, object handler, bool handledEventsToo) - 注册一个路由事件,注意最后一个参数:true 代表即使子辈 TappedRoutedEventArgs.Handled = true 也不会影响此元素事件的触发
 *     RemoveHandler(RoutedEvent routedEvent, object handler) - 移除指定的路由事件
 *     
 *     
 * RoutedEventArgs - 路由事件参数(有 n 多的派生类)
 *     OriginalSource - 引发此路由事件的对象
 * 
 * TappedRoutedEventArgs - Tapped 事件参数(继承自 RoutedEventArgs,详细说明请参见 /Controls/BaseControl/DependencyObjectDemo/TapDemo.xaml)
 *     Handled - 是否将路由事件标记为已处理
 *         true - 不再冒泡
 *         false - 继续冒泡
 *         
 *         
 * 本例用于演示 UIElement 的路由事件的注册,路由事件的冒泡,命中测试的可见性   
 */

using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;


namespace Windows10.Controls.BaseControl.UIElementDemo
{
    public sealed partial class EventDemo : Page
    {
        public EventDemo()
        {
            this.InitializeComponent();

            // 为 borderRed 注册一个 TappedEventHandler 路由事件(注意最后一个参数:true 代表即使子辈 TappedRoutedEventArgs.Handled = true 也不会影响此元素事件的触发)
            borderRed.AddHandler(UIElement.TappedEvent, new TappedEventHandler(borderRed_Tapped), true);
        }

        private void borderRed_Tapped(object sender, TappedRoutedEventArgs e)
        {
            lblMsg.Text += "borderRed tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;
        }

        private void borderGreen_Tapped(object sender, TappedRoutedEventArgs e)
        {
            lblMsg.Text += "borderGreen tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;
        }

        private void borderBlue_Tapped(object sender, TappedRoutedEventArgs e)
        {
            lblMsg.Text += "borderBlue tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;

            // 不会再冒泡,也就是说 borderGreen 无法响应 Tapped 事件,但是 borderRed 注册 Tapped 事件时 handledEventsToo = true,所以 borderRed 会响应 Tapped 事件
            e.Handled = true;
        }

        private void borderOrange_Tapped(object sender, TappedRoutedEventArgs e)
        {
            lblMsg.Text += "borderOrange tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;
        }

        private void borderPurple_Tapped(object sender, TappedRoutedEventArgs e)
        {
            // 不会响应此事件,因为 borderPurple 的 IsHitTestVisible = false
            lblMsg.Text += "borderPurple tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;
        }

        private void borderYellow_Tapped(object sender, TappedRoutedEventArgs e)
        {
            // 不会响应此事件,因为 borderYellow 的爸爸 borderPurple 的 IsHitTestVisible = false
            lblMsg.Text += "borderYellow tapped, originalSource: " + (e.OriginalSource as FrameworkElement).Name;
            lblMsg.Text += Environment.NewLine;
        }
    }
}



OK
[源码下载]

目录
相关文章
|
5月前
|
Windows
windows开启路由转发
windows开启路由转发
466 0
|
7月前
|
JavaScript 前端开发 PHP
【Vue+NodeJS】vue路由及NodeJS环境搭建(Windows版)
Node.js是一个基于Chrome V8引擎构建的JavaScript运行时环境使用了一个事件驱动、非阻塞式I/O 的模型;可以让JavaScript在服务器端运行,它让JavaScript成为与PHP、Python、Perl、Ruby等服务端语言平起平坐的脚本语言。相对于传统的JavaScript运行环境(如浏览器),Node.js具有以下特点:事件驱动:Node.js使用事件驱动的非阻塞I/O模型,使得在处理大量并发请求时效率更高。单线程。
|
消息中间件 安全 API
C#实现操作Windows窗口句柄:SendMessage/PostMessage发送系统消息、事件和数据【窗口句柄总结之二】
SendMessage/PostMessage API 可以实现发送系统消息,这些消息可以定义为常见的鼠标或键盘事件、数据的发送等各种系统操作......
3744 1
C#实现操作Windows窗口句柄:SendMessage/PostMessage发送系统消息、事件和数据【窗口句柄总结之二】
|
4月前
|
JavaScript Linux C#
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
【傻瓜级JS-DLL-WINCC-PLC交互】1.C#用windows窗体控件创建.net控件
65 0
|
4月前
|
XML Arthas Java
Windows【工具 04】WinSW官网使用说明及实例分享(将exe和jar注册成服务)实现服务器重启后的服务自动重启
Windows【工具 04】WinSW官网使用说明及实例分享(将exe和jar注册成服务)实现服务器重启后的服务自动重启
113 0
|
4月前
|
监控 安全 API
7.2 Windows驱动开发:内核注册并监控对象回调
在笔者上一篇文章`《内核枚举进程与线程ObCall回调》`简单介绍了如何枚举系统中已经存在的`进程与线程`回调,本章`LyShark`将通过对象回调实现对进程线程的`句柄`监控,在内核中提供了`ObRegisterCallbacks`回调,使用这个内核`回调`函数,可注册一个`对象`回调,不过目前该函数`只能`监控进程与线程句柄操作,通过监控进程或线程句柄,可实现保护指定进程线程不被终止的目的。
30 0
7.2 Windows驱动开发:内核注册并监控对象回调
|
10月前
|
Windows
Windows编程基础,第一个Windows程序,注册窗口,创建窗口(下)
Windows编程基础,第一个Windows程序,注册窗口,创建窗口
|
10月前
|
编译器 API 开发工具
Windows编程基础,第一个Windows程序,注册窗口,创建窗口(上)
Windows编程基础,第一个Windows程序,注册窗口,创建窗口
|
11月前
|
C++ Windows
C++ Windows窗口程序:子窗口控件之按钮类button
C++ Windows窗口程序:子窗口控件之按钮类button
555 0
|
开发者 Python Windows
windows python web route 路由
windows python web route 路由
windows python web route 路由

热门文章

最新文章