1、 internal TouchState TouchState get; public KinectTouchDevice(int id, PresentationSource source): base(id) this.Position = new Point(); this.TouchState = TouchState.Up; this.SetActiveSource(source); public void Touch(Point position) /记录第一次触摸时间 if (!this.firstTouch.HasValue) this.firstTouch = DateTim
2、e.Now; return; /如果不是第一次点击,但两次间隔小于100毫秒,则认为是一次点击,不做处理 else if (DateTime.Now.Subtract(this.firstTouch.Value).TotalMilliseconds < 100) this.Position = position;this.IsActive) this.Activate(); if (this.TouchState != TouchState.Down) this.Dispatcher.Invoke(new Func&bool>(this.ReportDown); this.Touc
3、hState = TouchState.Down; else(this.ReportMove); public void NoTouch() this.firstTouch = null; if (TouchState = TouchState.Down)(this.ReportUp); public override TouchPointCollection GetIntermediateTouchPoints(IInputElement relativeTo) return new TouchPointCollection(); public override TouchPoint Get
4、TouchPoint(IInputElement relativeTo) var point = this.Position; if (relativeTo != null) /获取当前点击位置 point = this.ActiveSource.RootVisual.TransformToDescendant(Visual)relativeTo).Transform(point); return new TouchPoint(this, point, new Rect(point, new Size(1, 1), TouchAction.Move); public void Dispose(
5、) if (this.IsActive) this.Deactivate(); 这是一个点,如何模拟一个面板呢,所以需要建立包含这一个点的集合的新类,名为KinectTouchDevice,详细代码如下public class KinectMultiTouchDevice : IDisposable /触控数据源 private HandDataSource handDataSource; private PresentationSource presentationSource; /触控点集合,每一个点对应一个id private IDictionary&int, KinectTouchDe
6、vice& touchDevices; public Size TargetSize get; set; public KinectMultiTouchDevice(HandDataSource handDataSource, PresentationSource presentationSource, Size targetSize) this.presentationSource = presentationSource; this.TargetSize = targetSize; public KinectMultiTouchDevice(HandDataSource handDataS
7、ource, FrameworkElement area) this.touchDevices = new Dictionary&(); this.TargetSize = new Size(area.ActualWidth, area.ActualHeight); this.presentationSource = PresentationSource.FromVisual(area); this.handDataSource = handDataSource; /当数据源有新数据时,触发处理事件 this.handDataSource.NewDataAvailable += handDat
8、aSource_NewDataAvailable; area.SizeChanged += area_SizeChanged; private void handDataSource_NewDataAvailable(Object sender, HandCollectionEventArgs data) if (data.IsEmpty) ReportNoTouch(this.touchDevices.Values); var touchedDevices = this.ReportTouches(data); this.ReportNoTouch(this.touchDevices.Val
9、ues.Except(touchedDevices); private void area_SizeChanged(object sender, SizeChangedEventArgs e) this.TargetSize = e.NewSize; private IList&KinectTouchDevice& ReportTouches(HandCollectionEventArgs data) var touchedDevices = new List& foreach (var hand in data.Hands) var device = this.GetDevice(hand.
10、Id); var pointOnPresentationArea = this.MapToPresentationArea(hand, new Size(this.handDataSource.Width, this.handDataSource.Height); device.Touch(pointOnPresentationArea); touchedDevices.Add(device); return touchedDevices; private void ReportNoTouch(IEnumerable& devices) foreach (var device in devic
11、es) device.NoTouch(); private KinectTouchDevice GetDevice(int index)this.touchDevices.ContainsKey(index) this.presentationSource.Dispatcher.Invoke(new Action() =& this.touchDevices.Add(index, new KinectTouchDevice(index, this.presentationSource); ); return this.touchDevicesindex; private Point MapTo
12、PresentationArea(HandData fingerPoint, Size originalSize) / return new Point(fingerPoint.X / originalSize.Width * this.TargetSize.Width, fingerPoint.Y / originalSize.Height * this.TargetSize.Height); return new Point(fingerPoint.X, fingerPoint.Y); this.handDataSource.NewDataAvailable -= handDataSour
13、ce_NewDataAvailable; foreach (var device in this.touchDevices.Values) device.Dispose(); 需要注意的是,上面代码中,touchDevices 是一个IDictionary& 型的对象,表示所有触控点的集合,每一个触控点有一个int型的id。代码中HandDataSource 类型的handDataSource,表示触发触控的数据源,在KinectMultiTouchDevice类的构造函数中,我们注册了handDataSource的NewDataAvailable事件,该事件会在每当从Kinect中获取每一帧
14、数据,且数据符合特定条件就会触发。HandDataSource类如下:public class HandDataSource public delegate void NewDataHandler&HandCollectionEventArgs&(Object sender,HandCollectionEventArgs data); public event NewDataHandler& NewDataAvailable; public int Width get; public int Height get; protected virtual void OnNewDataAvailab
15、le(HandCollectionEventArgs e) NewDataHandler& temp = NewDataAvailable; if (temp ! temp(this, e); public void RaiseNewDataEvent(List&HandData& handData) HandCollectionEventArgs e = new HandCollectionEventArgs(handData); OnNewDataAvailable(e); 以上部分就是使用模拟多点触控的核心代码了。(2)界面逻辑的编写 下面我们来看应用程序的前台代码。为了在界面上显示手的
16、位置,这里我们建立一个名为TouchControl的自定义控件,该控件很简单,里面包含一个椭圆形和一个label对象,用以表示当前手在屏幕上的位置,代码如下:&UserControl x:Class=KinectImageView.MultiTouch.TouchControl xmlns= xmlns:x=mc=http:/schemas.openxmlformats.org/markup-compatibility/2006d= mc:Ignorable=d d:DesignHeight=40DesignWidth= &Grid Width= Height=Ellipse Stroke=W
17、hite StrokeThickness=3/&Label Foreground= Name=Label HorizontalAlignment=Center VerticalAlignment=/Grid&/UserControl& 后台逻辑代码也很简单,只有一个带参的构造函数。public partial class TouchControl : UserControl public TouchControl() InitializeComponent(); public TouchControl(int id): this() this.Label.Content = id; 接下来就是
18、主界面了,为了简便,主界面上随意摆放了三张图片,用于我们使用Kinect来进行缩放平移旋转等操作,在页面的最底层添加了一个TouchControl自定义控件,用来显示手所在的位置。整个界面前端代码如下:Window x:KinectImageView.MainWindow Title=MainWindowc=clr-namespace:KinectImageView Closing=Window_Closing Loaded=Window_Loaded SizeToContent=WidthAndHeightGrid x:Name=LayoutRoot750 Width=1000Canvas
19、Name=mainCanvasImage Name=image Panel.ZIndex=642 IsManipulationEnabled=True200 Source=Images/flower.jpgImage.RenderTransform&MatrixTransform Matrix=1.5929750047527,0.585411309251951,-0.585411309251951,1.5929750047527,564.691807426081,79.4658072348299/Image.RenderTransform&/Image&image1641Images/flow
20、er2.jpg1.79780224775912,-1.1136472330559,1.1136472330559,1.79780224775912,45.6962327448951,205.029554723656 /&image2644Images/flower3.jpg2.41806325085411,-0.0527474549128994,0.0527474549128994,2.41806325085411,280.737615796121,292.420001677231/Canvas&fingerCanvas/Window& 下面来看看后台代码,WPF默认支持开发多点触控的程序,只
21、需要从写下面三个方法即可:protected override void OnManipulationStarting(ManipulationStartingEventArgs e) base.OnManipulationStarting(e); e.ManipulationContainer = mainCanvas; e.Handled = true;protected override void OnManipulationDelta(ManipulationDeltaEventArgs e) base.OnManipulationDelta(e); var element = e.S
22、ource as FrameworkElement; var transformation = element.RenderTransform as MatrixTransform; /获取缩放的中心点 Point center = new Point(element.ActualWidth / 2, element.ActualHeight / 2); var matrix = transformation = null ? Matrix.Identity : transformation.Matrix; center = matrix.Transform(center); /缩放 if (
23、e.DeltaManipulation.Scale.X & 0.5 & e.DeltaManipulation.Scale.Y&0.5e.DeltaManipulation.Scale.X&2&e.DeltaManipulation.Scale.Y&2) matrix.ScaleAt(e.DeltaManipulation.Scale.X, e.DeltaManipulation.Scale.Y, center.X, center.Y); /旋转 matrix.RotateAt(e.DeltaManipulation.Rotation, center.X, center.Y); /移动 if (center.X >
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1