迎接Multitouch时代系列之--传统的操作体验

本篇实际上就是MSDN上HOL的实现。不过一开始没找到那个HOL源码下载,于是自己做了一个,改了些功能和设计。本身并不复杂,程序的效果就是可以在窗口的一个区域上添加各种RenderTransform样式图片图片,用户能够通过鼠标对每一张图片进行拖拽和缩放,拖拽的图片能够被置顶。看下效果:

image  image

 

呵呵就是个山寨的“传统版智能照片桌面”。

设计说明

相当于做一个User Control,遵循MVVM,对外提供ViewModel接口,暴露ViewModel属性(因为我一开始把ViewModel提出来了,设置ViewModel属性会自动设置DataContext)。出于演示目的,只写了演示用到的功能,望大家谅解

TouchFirst.SaApp:WPF程序宿主,这里充当一个测试控件的程序。

TouchFirst.ControlsLib:控件库,含有两个控件:ImageDecorator,ImagesTable以及对外暴露的ViewModel接口。

用到了”Sa.Wpf.mvvm.ViewModel.dll”中的ViewModelBase类,这是以前写的一个ViewModel基类,实现INotifyPropertyChanged、IDispose。

类型说明

ImageDecorator:简单包装一个Image控件,方便使用者直接配置RotateTransform的Angle等属性。

IImageDecoratorViewModel:ImageDecorator适用的ViewModel,方便MVVM开发中使用。

ImageTables:能够承载若干个ImageDecorator,提供一个AddImage方法用于使用者添加图片。

IInputSupport:负责注册ImageTables的事件以及相应添加图片操作。

TraditionalInputSupport:实现IInputSupport,使控件支持传统的操作方式。

MultitouchSupport:实现IInputSupport,使控件支持触控操作方式

细节说明

 

ImageDecorator.xaml
< UserControl x:Class = " TouchFirst.ControlsLib.ImageDecorator "
    xmlns
= " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
    xmlns:x
= " http://schemas.microsoft.com/winfx/2006/xaml "  Background = " Transparent " >
    
< Image x:Name = " Img "  Source = " {Binding Path=ImagePath} "  Stretch = " Fill "  Height = " Auto "  Width = " Auto "  RenderTransformOrigin = " 0.5, 0.5 " >
        
< Image.RenderTransform >
            
< TransformGroup >
                
< RotateTransform Angle = " {Binding Path=Angle} " ></ RotateTransform >
                
< ScaleTransform ScaleX = " {Binding Path=ScaleX} "  ScaleY = " {Binding Path=ScaleY} " ></ ScaleTransform >
                
< TranslateTransform X = " {Binding Path=X} "  Y = " {Binding Path=Y} " ></ TranslateTransform >
            
</ TransformGroup >
        
</ Image.RenderTransform >
    
</ Image >
</ UserControl >

 

使用绑定时所要遵循的接口

IImageDecoratorViewModel
namespace  TouchFirst.ControlsLib
{
    
public   interface  IImageDecoratorViewModel
    {
        
#region  Presentation Properties Contract
        ImageSource ImagePath { 
get set ; }
        
double  ScaleX {  get set ; }
        
double  ScaleY {  get set ; }
        
double  X {  get set ; }
        
double  Y {  get set ; }
        
double  Angle {  get set ; }
        
#endregion
    }
}

 

 

控件行为接口

IInputSupport

namespace  TouchFirst.ControlsLib.External
{
    
public   interface  IInputSupport
    {
        
///   <summary>
        
///  注册UI的事件
        
///   </summary>
        
///   <param name="control"> 承载图片的Canvas容器 </param>
         void  Register(UIElement control, Canvas OutterContainer);
        
///   <summary>
        
///  增加图片路径
        
///   </summary>
        
///   <param name="path"> 图片路径 </param>
         void  AddImage( string  path);
    }
}

 

控件行为对传统输入设备的实现

 

TraditionalInputSupport
namespace  TouchFirst.ControlsLib.External
{
    
public   class  TraditionalInputSupport : IInputSupport
    {
        
#region  Fields
        
private  UIElement _control;
        
private  Point _prevLocation;
        
private  ImageDecorator _image;
        
private  Canvas _outterContainer;
        
#endregion

        
#region  IInputSupport 成员
        
public   void  Register(System.Windows.UIElement control, Canvas outterContainer)
        {
            _control 
=  control;
            _outterContainer 
=  outterContainer;
            control.MouseLeftButtonDown 
+=  MouseLeftButtonDownHandler;
            control.MouseMove 
+=  MouseMoveHandler;
            control.MouseLeftButtonUp 
+=  MouseLeftButtonUpHandler;
            control.MouseWheel 
+=  MouseWheelHandler;
        }
        
public   void  AddImage( string  filePath)
        {
            ImageDecorator image 
=   new  ImageDecorator() { ImagePath  =   new  BitmapImage( new  Uri(filePath)) };
            
// RandomPropertyGenerator.Configure(image);
            image.SetValue(Canvas.LeftProperty,  1.0 );
            image.SetValue(Canvas.TopProperty, 
1.0 );
            _outterContainer.Children.Add(image);
        }
        
#endregion

        
#region  Event Handler
        
private   void  MouseLeftButtonDownHandler( object  sender, MouseButtonEventArgs args)
        {
            _prevLocation 
=  args.GetPosition(_control);
            _image 
=  findImage();
            takeItFront(_image);
        }

        
private   void  MouseMoveHandler( object  sender, MouseEventArgs args)
        {
            
if  (args.LeftButton  ==  MouseButtonState.Released  ||  _image  ==   null )
                
return ;
            Point currentLocation 
=  args.GetPosition(_control);
            
double  offsetX  =  currentLocation.X  -  _prevLocation.X;
            
double  offsetY  =  currentLocation.Y  -  _prevLocation.Y;
            
double  prevX  =  ( double )_image.GetValue(Canvas.LeftProperty);
            
double  prevY  =  ( double )_image.GetValue(Canvas.TopProperty);
            _image.SetValue(Canvas.LeftProperty, prevX 
+  offsetX);
            _image.SetValue(Canvas.TopProperty, prevY 
+  offsetY);
            _prevLocation 
=  currentLocation;
            Console.WriteLine(
" {0}, {1} " , prevX, prevY);
        }

        
private   void  MouseLeftButtonUpHandler( object  sender, MouseButtonEventArgs args)
        {
            
if (_image  !=   null )
            {
                
// takeItBehind(_image);
                _image  =   null ;
            }
        }

        
private   void  MouseWheelHandler( object  sender, MouseWheelEventArgs args)
        {
            Point location 
=  args.GetPosition(_control);
            ImageDecorator image 
=  findImage();
            
if  (image  ==   null )
                
return ;
            takeItFront(image);
            
double  scalingFactor  =   1   +  args.Delta  /   1000.0 ;
            image.ScaleX 
*=  scalingFactor;
            image.ScaleY 
*=  scalingFactor;
        }

        
private  ImageDecorator findImage()
        {
            var list 
=  _outterContainer.Children;
            
foreach (var elmt  in  list)
            {
                var uiElmt 
=  elmt  as  ImageDecorator;
                
if (uiElmt  ==   null )
                    
continue ;
                
if (uiElmt.IsMouseOver)
                {
                    
return  uiElmt;
                }
            }
            
return   null ;
        }
        
        
private   void  takeItFront(UIElement uiElmt)
        {
            
foreach (var elmt  in  _outterContainer.Children)
            {
                var uiElmt2 
=  elmt  as  UIElement;
                
if (uiElmt2  !=   null )
                {
                    takeItBehind(uiElmt2);
                }
            }
            uiElmt.SetValue(Canvas.ZIndexProperty, 
99 );
        }
        
private   void  takeItBehind(UIElement uiElmt)
        {
            uiElmt.SetValue(Canvas.ZIndexProperty, 
1 );
        }
        
#endregion
    }
}

源码放到SkyDrive上了

http://public.blu.livefilestore.com/y1pdolMU6PHGnZitRCJtTlxRH_3_p0HyAv1zgJ2SM0-SqIrb37oC1_S_Qcixp_zl6y8Z8lCG5-nYGpipZOHgSvW2w/TouchFirst.rar?download

在下一篇会讨论如何修改这个程序以支持使用触控、手势操作(不过我这里也没有那种触控设备,所以只能勉强纸上谈兵)。

你可能感兴趣的:(touch)