首页 > 其他分享 >触控:WPF捕捉触控事件

触控:WPF捕捉触控事件

时间:2024-03-04 19:33:05浏览次数:27  
标签:return eventInfo touchUi private touchPoint 捕捉 触控 WPF Math

1 注册触控事件

2 注册键盘事件

3 注册鼠标点击事件

4 注册鼠标滚轮事件

using System;
using System.Diagnostics;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace Windows
{
    /// <summary>
    /// 触控源
    /// </summary>
    public class TouchSourceCreator 
    {
        //触控界面
        private FrameworkElement _touchUi;
        private int _realScreenWidth;
        private int _realScreenHeight;
        private double _lastMoveX = Double.NaN;
        private double _lastMoveY = Double.NaN;
        //触发最小像素间隔
        private double _minimumInterval;
        // 双击时间阈值/ms
        private const int DoubleClickTimeMs = 400;
        private readonly Stopwatch _lastTouchDown = new Stopwatch();

        /// <summary>
        /// 初始化事件
        /// </summary>
        /// <param name="touchUi"></param>
        public TouchSourceCreator(FrameworkElement touchUi)
        {
            _touchUi = touchUi;
            // 注册触控事件
            touchUi.TouchDown -= CaptureTouchDown;
            touchUi.TouchDown += CaptureTouchDown;
            touchUi.TouchMove -= CaptureTouchMove;
            touchUi.TouchMove += CaptureTouchMove;
            touchUi.TouchUp -= CaptureTouchUp;
            touchUi.TouchUp += CaptureTouchUp;
            // 注册键盘事件
            if (Application.Current.MainWindow != null)
            {
                Application.Current.MainWindow.KeyDown -= CaptureKeyboardDown;
                Application.Current.MainWindow.KeyDown += CaptureKeyboardDown;
                Application.Current.MainWindow.KeyUp -= CaptureKeyboardUp;
                Application.Current.MainWindow.KeyUp += CaptureKeyboardUp;
            }
            //注册鼠标事
            touchUi.MouseLeftButtonDown -= CaptureMouseLeftButtonDown;
            touchUi.MouseLeftButtonDown += CaptureMouseLeftButtonDown;
            touchUi.MouseLeftButtonUp -= CaptureMouseLeftButtonUp;
            touchUi.MouseLeftButtonUp += CaptureMouseLeftButtonUp;
            touchUi.MouseMove -= CaptureMouseMoveEventData;
            touchUi.MouseMove += CaptureMouseMoveEventData;
            touchUi.MouseRightButtonDown -= CaptureMouseRightButtonDown;
            touchUi.MouseRightButtonDown += CaptureMouseRightButtonDown;
            touchUi.MouseRightButtonUp -= CaptureMouseRightButtonUp;
            touchUi.MouseRightButtonUp += CaptureMouseRightButtonUp;
            // 注册鼠标滚轮事件
            touchUi.MouseWheel -= CaptureMouseWheelData;
            touchUi.MouseWheel += CaptureMouseWheelData;
        }

        /// <summary>
        /// 初始化屏幕大小
        /// </summary>
        /// <returns></returns>
        public async Task<Task> InitRealScreenSizeAsync()
        {
            await Task.Delay(100);
            while (true)
            {
                _realScreenWidth = (int)_touchUi.ActualWidth;
                _realScreenHeight = (int)_touchUi.ActualHeight;
                if (_realScreenWidth == 0)
                    await Task.Delay(100);
                else
                {
                    _minimumInterval = Math.Min(_realScreenWidth, _realScreenHeight) * 0.01;
                    return Task.CompletedTask;
                }
            }
        }

        #region 触控事件

        private void CaptureTouchDown(object sender, TouchEventArgs e)
        {
            if (!CanSend) return;
            var touchPoint = e.GetTouchPoint(_touchUi);
            var eventInfo = new EventInfo
            {
                Type = 6,
                Event = 0,
                X = Math.Round(touchPoint.Position.X / _realScreenWidth, 3),
                Y = Math.Round(touchPoint.Position.Y / _realScreenHeight, 3)
            };
            _lastMoveX = touchPoint.Position.X;
            _lastMoveY = touchPoint.Position.Y;

            DeviceSource?.Invoke(eventInfo);
        }


        private void CaptureTouchUp(object sender, TouchEventArgs e)
        {
            if (!CanSend) return;
            if (_lastTouchDown.IsRunning && _lastTouchDown.ElapsedMilliseconds < DoubleClickTimeMs)
            {
                HandleDoubleClick(e);
                _lastTouchDown.Reset();
                return;
            }
            _lastTouchDown.Restart();

            var touchPoint = e.GetTouchPoint(_touchUi);
            var eventInfo = new EventInfo
            {
                Type = 6,
                Event = 1,
                X = Math.Round(touchPoint.Position.X / _realScreenWidth, 3),
                Y = Math.Round(touchPoint.Position.Y / _realScreenHeight, 3)
            };
            _lastMoveX = Double.NaN;
            _lastMoveY = Double.NaN;

            DeviceSource?.Invoke(eventInfo);
        }

        private void HandleDoubleClick(TouchEventArgs e)
        {
            var touchPoint = e.GetTouchPoint(_touchUi);
            var eventInfo = new EventInfo
            {
                Type = 7,
                Event = 1,
                X = Math.Round(touchPoint.Position.X / _realScreenWidth, 3),
                Y = Math.Round(touchPoint.Position.Y / _realScreenHeight, 3)
            };
            _lastMoveX = touchPoint.Position.X;
            _lastMoveY = touchPoint.Position.Y;

            DeviceSource?.Invoke(eventInfo);
        }

        private void CaptureTouchMove(object sender, TouchEventArgs e)
        {
            if (!CanSend) return;
            TouchPoint touchPoint = e.GetTouchPoint(_touchUi);
            var eventInfo = new EventInfo
            {
                Type = 6,
                Event = 4,
                X = Math.Round(touchPoint.Position.X / _realScreenWidth, 3),
                Y = Math.Round(touchPoint.Position.Y / _realScreenHeight, 3)
            };

            if (!double.IsNaN(_lastMoveX) && Math.Abs(_lastMoveX - touchPoint.Position.X) < _minimumInterval && Math.Abs(_lastMoveY - touchPoint.Position.Y) < _minimumInterval)
            {
                return;
            }
            _lastMoveX = touchPoint.Position.X;
            _lastMoveY = touchPoint.Position.Y;

            DeviceSource?.Invoke(eventInfo);
        }
        #endregion

        #region 鼠标事件
        private void CaptureMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!CanSend) return;
            if (e.StylusDevice != null) return;
            var eventInfo = new EventInfo
            {
                Type = 2,
                Event = 0,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(eventInfo);
        }
        private void CaptureMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!CanSend) return;
            if (e.StylusDevice != null) return;
            var codeType = new EventInfo
            {
                Type = 2,
                Event = 1,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(codeType);
        }
        private void CaptureMouseRightButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!CanSend) return;
            if (e.StylusDevice != null) return;
            var eventInfo = new EventInfo
            {
                Type = 3,
                Event = 0,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(eventInfo);
        }
        private void CaptureMouseRightButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (!CanSend) return;
            if (e.StylusDevice != null) return;
            var eventInfo = new EventInfo
            {
                Type = 3,
                Event = 1,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(eventInfo);
        }
        private void CaptureMouseMoveEventData(object sender, MouseEventArgs e)
        {
            if (!CanSend) return;
            if (e.StylusDevice != null) return;
            var pressedMouseButton = GetPressedType(true, e);
            if (pressedMouseButton.type == 0)
            {
                return;
            }
            var eventInfo = new EventInfo
            {
                Type = pressedMouseButton.type,
                Event = pressedMouseButton.eventType,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(eventInfo);
        }
        private void CaptureMouseWheelData(object sender, MouseWheelEventArgs e)
        {
            var eventInfo = new EventInfo
            {
                Type = 4,
                Event = e.Delta > 0 ? 2 : 3,
                X = Math.Round(e.GetPosition(_touchUi).X / _realScreenWidth, 3),
                Y = Math.Round(e.GetPosition(_touchUi).Y / _realScreenHeight, 3)
            };

            DeviceSource?.Invoke(eventInfo);
        }

        /// <summary>
        /// 获取按压类型
        /// </summary>
        /// <param name="move"></param>
        /// <param name="e"></param>
        /// <returns></returns>
        private (int type, int eventType) GetPressedType(bool move, MouseEventArgs e)
        {
            if (e.LeftButton == MouseButtonState.Pressed)
            {
                return move ? (1, 0) : (2, 0);
            }
            if (e.MiddleButton == MouseButtonState.Pressed)
            {
                return (4, 0);
            }
            if (e.RightButton == MouseButtonState.Pressed)
            {
                return (3, 0);
            }
            return (0, 0);
        }

        #endregion

        #region 键盘事件
        private void CaptureKeyboardDown(object sender, KeyEventArgs e)
        {
            if (!CanSend) return;

            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(e.Key); // 转换为虚拟键码
            var eventInfo = new EventInfo
            {
                Type = 5,
                Event = 0,
                Code = virtualKeyCode,
            };

            DeviceSource?.Invoke(eventInfo);
        }

        private void CaptureKeyboardUp(object sender, KeyEventArgs e)
        {
            if (!CanSend) return;
            int virtualKeyCode = KeyInterop.VirtualKeyFromKey(e.Key); // 转换为虚拟键码
            var eventInfo = new EventInfo
            {
                Type = 5,
                Event = 1,
                Code = virtualKeyCode,
            };

            DeviceSource?.Invoke(eventInfo);
        }
        #endregion

        private bool CanSend => _realScreenWidth != 0;

        /// <summary>
        /// 设备触发
        /// </summary>
        public event Action<EventInfo> DeviceSource;
    }
}

 

标签:return,eventInfo,touchUi,private,touchPoint,捕捉,触控,WPF,Math
From: https://www.cnblogs.com/terryK/p/18052488

相关文章

  • 解决WPF下popup不随着window一起移动的问题
    解决WPF下popup不随着window一起移动的问题_小戴BOTAOY演示博客(yii666.com)///<summary>///Popup帮助类,解决Popup设置StayOpen="True"时,移动窗体或者改变窗体大小时,Popup不随窗体移动的问题///</summary>publicclassPopopHelper{publicstaticDependency......
  • wpf中treeview和ICollectionView接口实现数据过滤
    privateICollectionView_collectionView;privatevoidbinddata(List<obj>list){//创建CollectionViewSource并绑定到TreeViewCollectionViewSourcecollectionViewSource=newCollectionViewSource{Source=li......
  • WPF Binding 绑定标记扩展
    参考绑定标记扩展Binding类环境软件/系统版本说明WindowsWindows10专业版22H219045.4046MicrosoftVisualStudioMicrosoftVisualStudioCommunity2022(64位)-17.6.5Microsoft.NetSDK8.0.101手动安装Microsoft.NetSDK7.0.306Mi......
  • VS2019 打包WPF安装程序
    说明最近开发了一个WPF的小工具,最初想发布成一个非安装版的可执行程序,发现有点困难,因为是基于.NetFramework4.7开发,还引用了一些其他库,WPF程序的运行是依赖.NetFramework环境的,所以必须提前安装。于是在官网上找到ClickOne的相关说明,可以把WPF打包成安装程序,当安装时会校......
  • WPF性能优化:Visual Studio性能分析工具使用介绍
    在硬件性能不断提升的现在,软件性能依旧是开发人员关注的重点。不同类型的程序关注的具体性能指标有所不同,服务器程序注重吞吐量,游戏引擎追求渲染效率,桌面程序则关注内存消耗以及界面加载效率和流畅性。当我们需要进行性能优化时,首先需要找到性能瓶颈。本文将介绍两个WPF性能优化......
  • WPF性能优化:性能分析工具
    在硬件性能不断提升的现在,软件性能依旧是开发人员关注的重点。不同类型的程序关注的具体性能指标有所不同,服务器程序注重吞吐量,游戏引擎追求渲染效率,桌面程序则关注内存消耗以及界面加载效率和流畅性。当我们需要进行性能优化时,首先需要找到性能瓶颈。本文将介绍两个WPF性能优化分......
  • WPF DataGrid交错行颜色
    代码如下<!-- AutoGenerateColumns="False"可以避免出现重复列 --><!-- CanUserAddRows="False"去除最后一行空白行 --><DataGridx:Name="datagrid"AlternationCount="2"AutoGenerateColumns="False"CanUserAddRow......
  • WPF DataGrid下的单元格嵌入CheckBox列表
    <DataGridWidth="auto"Height="auto"AutoGenerateColumns="False"CanUserAddRows="False"GridLinesVisibility="All">        <DataGrid.Columns><DataGridTempla......
  • 记一次WPF集成SemanticKernel+OneAPI+讯飞星火认知大模型实践
    开启OneAPI服务OneAPI介绍OpenAI接口管理&分发系统,支持Azure、AnthropicClaude、GooglePaLM2&Gemini、智谱ChatGLM、百度文心一言、讯飞星火认知、阿里通义千问、360智脑以及腾讯混元,可用于二次分发管理key,仅单可执行文件,已打包好Docker镜像,一键部署,开箱即用.Ope......
  • 搜维尔科技:OptiTrack 提供了性能最佳的动作捕捉平台
    OptiTrack动画我们的Prime系列相机和Motive软件相结合,产生了世界上最大的捕获量、最精确的3D数据和有史以来最高的相机数量。OptiTrack提供了性能最佳的动作捕捉平台,具有易于使用的制作工作流程以及运行世界上最大舞台所需的深度。无与伦比的3D精度我们的3D精度是业......