SnipperImages(Silverlight DEMO)控件设计之--Slider和ColorSlider

     在 上一篇文章中,介绍了CheckBox控件的开发方式,包括xaml和控件逻辑(cs代码控制xaml中UI元素)。
本文所要介绍的Slider控件在xaml上与CheckBox复杂度相似,比较底。而控件逻辑相对要复杂不少,这些
逻辑会在本文中进行介绍。

     好了,开始今天的正文。

     首先看一下这个演示页,如下:



  注:因为我从网上所获得的源码中Slider控件并没有全部开发完,起码在上面所示的垂直Slider只是粗

略的定义了xaml(其中某些值还有错误),而CS代码就少得更多了。本人在原有代码基础上,完成了垂直

Slider的开发,并修正了原有的CS代码中的BUG。


      而该控件的xaml代码如下所示(Slider.xaml):

< ControlTemplate  xmlns ="http://schemas.microsoft.com/client/2007"
                 xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"   >
  
< Grid  x:Name ="Part_Root"  Width ="200"  Height ="24" >
    
< Canvas  x:Name ="Part_Border"  Background ="Transparent" >
        
< Line  x:Name ='Part_Line'  StrokeThickness ="1"  Stroke ="Blue"  X1 ="4"  X2 ="196"  Y1 ="12"
              Y2
="12" />
        
< Path  x:Name ='Part_ThumbHorizontal'  Canvas.Top ='3'  Data ='M0,0 L16,0 L8,18z'  Fill ='Silver'
              Stroke
='Black' />
        
< Path  x:Name ='Part_ThumbVertical'  Canvas.Left ='3'  Visibility ="Collapsed"
              Data
='M0,0 L18,8 L0,16z'  Fill ='Silver'  Stroke ='Black' />
    
</ Canvas >
  
</ Grid >
</ ControlTemplate >


    从上面代码可以看出,Slider由四个主要元素组成:

   Part_Border:用于绘制背景色(如ColorSlider控件的背景色)

Part_Line:用于绘制滑动的中线

Part_ThumbHorizontal:用于绘制水平滑块

Part_ThumbVertical:用于绘制垂直滑块



  下面这张图标识了各元素在控件中的对应位置和关系:

 

 



      对应上图,下面是ColorSlider的xaml代码:

< ControlTemplate  xmlns ="http://schemas.microsoft.com/client/2007"
                 xmlns:x
="http://schemas.microsoft.com/winfx/2006/xaml"   >
< Grid  x:Name ="Part_Root"  Width ='200'  Height ='24' >
    
< Canvas  x:Name ='Part_Border' >
      
< Canvas.Background >
        
< LinearGradientBrush  x:Name ="GradientBrush"   StartPoint ="0,0"  EndPoint ="1,0" >
          
< GradientStop  Color ="#FF000000"  Offset ="0" />
          
< GradientStop  Color ="#FFFF0000"  Offset ="0.143" />
          
< GradientStop  Color ="#FF00FF00"  Offset ="0.286" />
          
< GradientStop  Color ="#FF0000FF"  Offset ="0.429" />
          
< GradientStop  Color ="#FF00FFFF"  Offset ="0.571" />
          
< GradientStop  Color ="#FFFF00FF"  Offset ="0.714" />
          
< GradientStop  Color ="#FFFFFF00"  Offset ="0.857" />
          
< GradientStop  Color ="#FFFFFFFF"  Offset ="1" />
        
</ LinearGradientBrush >
      
</ Canvas.Background >
      
< Line  x:Name ='Part_Line'  StrokeThickness ="1"  Stroke ="Blue"  X1 ="4"  X2 ="196"  Y1 ="12"  Y2 ="12" />
      
< Path  x:Name ='Part_ThumbHorizontal'  Canvas.Top ='3'  Data ='M0,0 L16,0 L8,18z'  Fill ='Silver'
             Stroke
='Black' />
      
< Path  x:Name ='Part_ThumbVertical'  Canvas.Left ='3'  Visibility ="Collapsed"
             Data
='M0,0 L18,8 L0,16z'  Fill ='Silver'  Stroke ='Black' />
   
</ Canvas >
  
</ Grid >
</ ControlTemplate >


      说完了xaml,下面开始介绍cs控件逻辑代码。

      首先要说的是一个枚举类型,用于标识滑动方向(垂直或水平):

///   <summary>
///  滑动条方向类型
///   </summary>
public   enum  SliderOrientation
{
    
///   <summary>
    
///  垂直
    
///   </summary>
    Vertical,
    
///   <summary>
    
///  水平
    
///   </summary>
    Horizontal
}


      而控件的核心代码如下(有关我修改或添加的部分已通过注释说明):


///   <summary>
///  滑动条控制类
///   </summary>
[TemplatePart(Name  =   " Part_Root " , Type  =   typeof (Panel))]
[TemplatePart(Name 
=   " Part_Border " , Type  =   typeof (FrameworkElement))]
[TemplatePart(Name 
=   " Part_ThumbHorizontal " , Type  =   typeof (FrameworkElement))]
[TemplatePart(Name 
=   " Part_ThumbVertical " , Type  =   typeof (FrameworkElement))]
[TemplatePart(Name 
=   " Part_Line " , Type  =   typeof (FrameworkElement))]
public   partial   class  Slider : Control
{
    
public  Slider()
    {
        
string  xaml  =  ResourceHelper.GetTemplate( this .GetType());
        ControlTemplate template 
=  (ControlTemplate)XamlReader.Load(xaml);
        
this .Template  =  template;
        
this .ApplyTemplate();
    }

    
public   event  EventHandler ValueChanged;

    
///   <summary>
    
///  值改变时
    
///   </summary>
     protected   void  OnValueChanged()
    {
        
if  (ValueChanged  !=   null )
        {
            
// 执行绑定代码
            ValueChanged( this new  EventArgs());
        }
    }

    
///   <summary>
    
///  绑定模板元素及相应事件
    
///   </summary>
     public   override   void  OnApplyTemplate()
    {
        Part_Root 
=  (Panel)GetTemplateChild( " Part_Root " );
        Part_Line 
=  (Line)GetTemplateChild( " Part_Line " );
        Part_ThumbHorizontal 
=  (FrameworkElement)GetTemplateChild( " Part_ThumbHorizontal " );
        Part_ThumbVertical 
=  (FrameworkElement)GetTemplateChild( " Part_ThumbVertical " );
        Part_Border 
=  (FrameworkElement)GetTemplateChild( " Part_Border " );

        Part_ThumbHorizontal.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(Part_Thumb_MouseLeftButtonDown);
        Part_ThumbHorizontal.MouseMove 
+=   new  MouseEventHandler(Part_Thumb_MouseMove);
        Part_ThumbHorizontal.MouseLeftButtonUp 
+=   new  MouseButtonEventHandler(Part_Thumb_MouseLeftButtonUp);
        Part_ThumbVertical.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(Part_Thumb_MouseLeftButtonDown);
        Part_ThumbVertical.MouseMove 
+=   new  MouseEventHandler(Part_Thumb_MouseMove);
        Part_ThumbVertical.MouseLeftButtonUp 
+=   new  MouseButtonEventHandler(Part_Thumb_MouseLeftButtonUp);
        Part_Root.MouseLeave 
+=   new  MouseEventHandler(Part_Root_MouseLeave);
        Part_Root.MouseEnter 
+=   new  MouseEventHandler(Part_Root_MouseEnter);
        Part_Border.MouseLeftButtonDown 
+=   new  MouseButtonEventHandler(Part_Border_MouseLeftButtonDown);           
    }

    
///   <summary>
    
///  当鼠标在滑动条(不是滑块)上点击时,将滑块设置到鼠标点击位置
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Border_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
    {
        
// 当不是滑块时
         if  (e.Source  !=  Part_ThumbHorizontal  &&  e.Source  !=  Part_ThumbVertical)
        {
            Point newPos 
=  e.GetPosition(Part_Root);
            {
                
if  (_orientation  ==  SliderOrientation.Horizontal)
                {
                    Part_ThumbHorizontal.SetValue(Canvas.LeftProperty, Math.Min(newPos.X,
                         Part_Border.ActualWidth 
-  Part_ThumbHorizontal.ActualWidth));
                }
                
else
                {
                    Part_ThumbVertical.SetValue(Canvas.TopProperty, Math.Min(newPos.Y,
                         Part_Border.ActualHeight 
-  Part_ThumbVertical.ActualHeight));
                }
                
this .OnValueChanged();
            }
        }
    }
    
///   <summary>
    
///  鼠标进入滑动条区域
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Root_MouseEnter( object  sender, MouseEventArgs e)
    {
        
if  (hasCapture)
        {
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                Part_ThumbHorizontal.CaptureMouse();
            }
            
else
            {
                Part_ThumbVertical.CaptureMouse();
            }
        }
        
else
        {
            _mouseDownValue 
=   - 1 ;
        }
    }

    
///   <summary>
    
///  鼠标离开滑动条区域
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Root_MouseLeave( object  sender, MouseEventArgs e)
    {
        
if  (_orientation  ==  SliderOrientation.Horizontal)
        {
            Part_ThumbHorizontal.ReleaseMouseCapture();
        }
        
else
        {
            Part_ThumbVertical.ReleaseMouseCapture();
        }
    }
    
///   <summary>
    
///  鼠标按下滑动块
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Thumb_MouseLeftButtonDown( object  sender, MouseButtonEventArgs e)
    {
        FrameworkElement thumb 
=  (FrameworkElement)sender;
        
// 在当前滑动块上设置“鼠标捕获”
        thumb.CaptureMouse();
        hasCapture 
=   true ;
        _thumbMouseDown 
=  e.GetPosition(Part_Root);
        
        
if  (_orientation  ==  SliderOrientation.Horizontal) // 当为水平方向时
        {
            
// 获取滑动块的“左”值属性
            _mouseDownValue  =  ( double )thumb.GetValue(Canvas.LeftProperty);
        }
        
else
        {
            
// 获取滑动块的“顶”值属性
            _mouseDownValue  =  ( double )thumb.GetValue(Canvas.TopProperty);
        }
    }

    
///   <summary>
    
///  鼠标拖动滑动块移动
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Thumb_MouseMove( object  sender, MouseEventArgs e)
    {
        FrameworkElement thumb 
=  (FrameworkElement)sender;
        Point newPos 
=  e.GetPosition(Part_Root);
        
if  (_orientation  ==  SliderOrientation.Horizontal)
        {
            
double  newX  =  newPos.X  -  _thumbMouseDown.X  +  _mouseDownValue;
            
if  (_mouseDownValue  !=   - 1   &&
                newX 
<=  Part_Border.ActualWidth  -   8   &&
                newX 
>=   - 8 )
            {
                thumb.SetValue(Canvas.LeftProperty, newX);
// 仅在水平方向上移动
                 this .OnValueChanged();
            }
        }
        
else
        {
            
double  newY  =  newPos.Y  -  _thumbMouseDown.Y  +  _mouseDownValue;
            
if  (_mouseDownValue  !=   - 1   &&
                newY 
<=  Part_Border.ActualHeight  -   8   &&
                newY 
>=   - 8 )
            {
                thumb.SetValue(Canvas.TopProperty, newY);
// 仅在垂直方向上移动
                 this .OnValueChanged();
            }
        }
    }

    
///   <summary>
    
///  鼠标拖动结束
    
///   </summary>
    
///   <param name="sender"></param>
    
///   <param name="e"></param>
     void  Part_Thumb_MouseLeftButtonUp( object  sender, MouseButtonEventArgs e)
    {
        FrameworkElement thumb 
=  (FrameworkElement)sender;
        _mouseDownValue 
=   - 1 ;
        thumb.ReleaseMouseCapture();
        hasCapture 
=   false ;
    }

    
///   <summary>
    
///  设置滑动条的宽
    
///   </summary>
     public   double  SliderWidth
    {
        
get  {  return  Part_Root.Width; }
        
set
        {
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                
// 水平方向上设置
                Part_Line.X2  =  value;
                Part_Root.Width 
=  value;
            }
            
else
            {
                
// 获取Slider.xaml中的相应属性配置
                Part_Line.X1  =  Part_Line.X2  =  value  /  2d;
                Part_ThumbVertical.SetValue(Canvas.LeftProperty, value 
/  2d  -  Part_ThumbVertical.ActualWidth  /  2d);
            }
        }
    }

    
///   <summary>
    
///  设置滑动条的高度
    
///   </summary>
     public   double  SliderHeight
    {
        
get  {  return  Part_Root.Height; }
        
set
        {
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                
// 获取Slider.xaml中的相应属性配置
                Part_Line.Y1  =  Part_Line.Y2  =  value  /  2d;
                Part_ThumbHorizontal.SetValue(Canvas.TopProperty, value 
/  2d  -  Part_ThumbHorizontal.ActualHeight  /  2d);
            }
            
else
            {
                
// 垂直方向上设置
                Part_Line.Y2  =  value;
                Part_Root.Height 
=  value;
            }
        }
    }

    
///   <summary>
    
///  获取或设置滑动条的当前值
    
///   </summary>
     public   double  Value
    {
        
get
        {
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                
double  val  =  ( double )Part_ThumbHorizontal.GetValue(Canvas.LeftProperty)  /  (Part_Root.ActualWidth  -   8 );
                val 
=  Math.Max(0d, val);
                val 
=  Math.Min(val, 1d);
                
return  val;
            }
            
else
            {
                
double  val  =  ( double )Part_ThumbVertical.GetValue(Canvas.TopProperty)  /  (Part_Root.ActualHeight  -   8 );
                val 
=  Math.Max(0d, val);
                val 
=  Math.Min(val, 1d);
                
return  val;
            }
        }
        
set
        {
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                Part_ThumbHorizontal.SetValue(Canvas.LeftProperty, value 
*  (Part_Root.Width  -   8 ));
            }
            
else
            {
                Part_ThumbVertical.SetValue(Canvas.TopProperty, value 
*  (Part_Root.Height  -   8 ));
            }
        }
    }

    
///   <summary>
    
///  获取或设置滑动条的方向,参见SliderOrientation
    
///   </summary>
     public   SliderOrientation Orientation
    {
        
get  {  return  _orientation; }
        
set
        {
            _orientation 
=  value;
            
if  (_orientation  ==  SliderOrientation.Horizontal)
            {
                Part_ThumbVertical.Visibility 
=  Visibility.Collapsed;
                Part_ThumbHorizontal.Visibility 
=  Visibility.Visible;
                Part_Line.Y1 
=  Part_Line.Y2  =  Part_Root.Height  /  2d;
                Part_Line.X1 
=  0d;
                Part_Line.X2 
=  Part_Root.Width;
            }
            
else
            {
                
// 注:此处代码为本人所加,用于当为垂直方向时,交换Width与Height的值
                 double  temp  =  Part_Root.Width;
                Part_Root.Width 
=  Part_Root.Height;
                Part_Root.Height 
=  temp;                    

                Part_ThumbHorizontal.Visibility 
=  Visibility.Collapsed;
                Part_ThumbVertical.Visibility 
=  Visibility.Visible;
                Part_Line.X1 
=  Part_Line.X2  =  Part_Root.Width  /  2d;
                Part_Line.Y1 
=  0d;
                Part_Line.Y2 
=  Part_Root.Height;
            }
        }
    }

    
#region  UI元素声明
    
protected  Panel Part_Root;
    
protected  Line Part_Line;
    
protected  FrameworkElement Part_Border, Part_ThumbVertical, Part_ThumbHorizontal;
    
#endregion

    
protected  Point _thumbMouseDown;
    
protected   double  _mouseDownValue  =   - 1 ;
    
protected   bool  hasCapture  =   false ;
    
protected  SliderOrientation _orientation  =  SliderOrientation.Horizontal;
}


       下面代介绍的是ColorSlider控件的控件逻辑cs文件(详情看注释):

///   <summary>
///  颜色滑动条控制
///   </summary>
public   partial   class  ColorSlider : Slider
{
    
public  ColorSlider()
    {
        
string  xaml  =  ResourceHelper.GetTemplate( this .GetType());
        ControlTemplate template 
=  (ControlTemplate)XamlReader.Load(xaml);
        
this .Template  =  template;
        
base .ApplyTemplate();
    }
    
///   <summary>
    
///  该方法为本人所加,用户当滑动条方向为“垂直”时,重新设置“GradientBrush”的“EndPoint”属性
    
///   </summary>
     public   new  SliderOrientation Orientation
    {
        
get  {  return   base .Orientation; }
        
set
        {
            
base .Orientation  =  value;
            
// 当为垂直方向时
             if  (value  ==  SliderOrientation.Vertical)
            {
                ((LinearGradientBrush)GetTemplateChild(
" GradientBrush " )).EndPoint  =   new  Point( 0 1 );
            }               
        }
    }
    

///   <summary>
///  获取颜色值
///   </summary>
///   <returns></returns>
     public  Color GetColor()
    {
        
return   this .GetColor( 255 );
    }

    
///   <summary>
    
///  将滑动条值(Value)转换为ARGB 颜色值并返回
    
///   </summary>
    
///   <param name="alpha"> alpha通道,该值介于0到255 </param>
    
///   <returns> ARGB 颜色值 </returns>
     public  Color GetColor( byte  alpha)
    {
        Color color;
        
double  value  =   this .Value;

        
//  将滑动条的值转换为 ARGB 颜色值
         if  (value  <   0.143d )
        {
            color 
=  Color.FromArgb(alpha, ( byte )Math.Floor((value  *  256d)  /   0.143d ),  0 0 );
        }
        
else   if  (value  <   0.286d )
        {
            color 
=  Color.FromArgb(alpha, ( byte )Math.Floor(256d  *  ( 0.286d   -  value)  /   0.143d ), 
                              (
byte )Math.Floor(256d  *  (value  -   0.143d /   0.143d ),  0 );
        }
        
else   if  (value  <   0.429 )
        {
            color 
=  Color.FromArgb(alpha,  0 , ( byte )Math.Floor(256d  *  ( 0.429d   -  value)  /   0.143d ), 
                              (
byte )Math.Floor(256d  *  (value  -   0.286d /   0.143d ));
        }
        
else   if  (value  <   0.571 )
        {
            color 
=  Color.FromArgb(alpha,  0 , ( byte )Math.Floor(256d * (value - 0.429d ) / 0.143d ),  255 );
        }
        
else   if  (value  <   0.714 )
        {
            color 
=  Color.FromArgb(alpha, ( byte )Math.Floor(256d  *  (value  -   0.571d /   0.143d ), 
                             (
byte )Math.Floor(256d  *  ( 0.714d   -  value)  /   0.143d ),  255 );
        }
        
else   if  (value  <   0.857 )
        {
            color 
=  Color.FromArgb(alpha,  255 , ( byte )Math.Floor(256d  *  (value  -   0.714d /   0.143d ), 
                             (
byte )Math.Floor(256d  *  ( 0.857d   -  value)  /   0.143d ));
        }
        
else
        {
            color 
=  Color.FromArgb(alpha,  255 255 , ( byte )Math.Floor(256d  *  (value  -   0.857d /   0.143d ));
        }
        
return  color;
    }
}


      接着再来看一下如何使用这两个控件(也就是本文第一张图所演示的效果),其page逻辑代码如下:

public   partial   class  Page2 : UserControl
{
 
public  Page2()
     {
            InitializeComponent();
            
            
            
#region  Slider测试代码,加载图片并添加演示缩放旋转的Transform

            
string  baseUri  =  Application.Current.Host.Source.AbsoluteUri.Substring( 0
                                    Application.Current.Host.Source.AbsoluteUri.LastIndexOf(
" / " ));
            currentImage.SetValue(Image.SourceProperty, 
new  BitmapImage(
                                     
new  Uri(String.Concat(baseUri,  " /../Images/j0433157.jpg " ))));
            TransformGroup transforms 
=   new  TransformGroup();
            transforms.Children.Add(
new  ScaleTransform());
            transforms.Children.Add(
new  RotateTransform());
            currentImage.RenderTransform 
=  transforms;
            currentImage.RenderTransformOrigin 
=   new  Point( 0.5 0.5 );

            
#endregion

    }

    
#region  Slider示例代码
    
void  ColorSlider_ValueChanged( object  sender, EventArgs e)
    { 
       
// 水平Slider设置背景色
        SliderPanel.Background  =   new  SolidColorBrush(ColorSlider.GetColor());
    }

    
void  ColorSlider2_ValueChanged( object  sender, EventArgs e)
    {
      
// 垂直Slider设置背景色
        SliderPanel2.Background  =   new  SolidColorBrush(ColorSlider2.GetColor());
    }

    
private   void  opacitySlider_ValueChanged( object  sender, EventArgs e)
    { 
      
// 设置图像的Opacity属性
        currentImage.Opacity  =  1d  -  opacitySlider.Value;
    }

    
    
private   void  transformSlider_ValueChanged( object  sender, EventArgs e)
    {
      
// 设置旋转属性
        ((RotateTransform)((TransformGroup)currentImage.RenderTransform).Children[ 1 ]).Angle  =  
                                                     (transformSlider.Value 
-   0.5d *  720d;
// 设置缩放属性
        ((ScaleTransform)((TransformGroup)currentImage.RenderTransform).Children[ 0 ]).ScaleX  =  
                                                     transformSlider.Value 
*  2d;
        ((ScaleTransform)((TransformGroup)currentImage.RenderTransform).Children[
0 ]).ScaleY  =  
                                                     transformSlider.Value 
*  2d;
    }
    
#endregion
}


     好了,今天的内容就先到这里了。

     tag:silverlight,slider,colorslider,imagesnipper

     作者:代震军,daizhj

     原文链接:http://www.cnblogs.com/daizhj/archive/2008/09/04/1284228.html

     源码下载,请 点击这里:)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值