• 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(thisnew 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(01);
                }               
            }
        }
        

    /// <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), 00);
            }
            
    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, 255255, (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.50.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

         源码下载,请点击这里:)
  • 相关阅读:
    当别人没说好,那么事就没达成协定
    设计模式(六):原型模式
    《一拳超人》观后感
    设计模式(五):中介者模式
    设计模式(四):单例模式与工厂模式
    设计模式(二):构造器模式与模块模式
    设计模式(一):概念小谈
    CSS代码记录
    java之如何实现调用启动一个可执行文件,exe
    file类之目录
  • 原文地址:https://www.cnblogs.com/daizhj/p/1284228.html
Copyright © 2020-2023  润新知