zoukankan      html  css  js  c++  java
  • 推荐并简要分析一个silverlight的相册DEMOImageSnipper(V2)

         在前一阵子,我在网上找到了这个相册DEMO,其不仅支持图相册图片的顺(逆)序浏览,还支持简单的图

    片处理(放大缩小Zoom,旋转Rotate,透明Transparency),在图片上打水印以及使用Ink在图片上涂鸭。

       在线演示:

         http://silverlight.services.live.com/invoke/72193/ImageSnipperV2/iframe.html

      下面就是它的一些演示截图。
      
         首先是缩放,旋转和透明处理:


      

         然后是文字水印处理:

      

      然后是使用Ink的涂鸭:


      

         相信做为一个相册(图片浏览)的基本功能已经没什么问题了。

         下面来看一下这个DEMO的类图,如下:


      

         上图中的左半部用红框标识的区域是其控件设计类,因为本DEMO中所使用的控件如:按钮,滑动条,
    复选框等均未使用Silverlight中所提供的控件,而是自己绘制并定义事件。因此这是我对该DEMO感兴趣的
    另一个原因。而右侧则是一些工具类或图片处理类,如处理图片移动的MovableImage和TextBlock移动的
    MovableTextBlock等。

      下面先简要介绍一下其中的Button按钮控件的设计思路。因为其继承自ButtonBase,所以有必要先看
    一下ButtonBase的代码声明,下面是xaml中的内容:

    <ControlTemplate xmlns="http://schemas.microsoft.com/client/2007"
                     xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" >
      
    <Grid x:Name="Part_Root" MouseEnter="btnClearMouseEnter" MouseLeave="btnClearMouseLeave" 
             MouseLeftButtonDown
    ="btnClearMouseDown" MouseLeftButtonUp="btnClearMouseUp">
        
    <Grid.Resources>
          
    <Storyboard x:Name="Part_MouseEnter"/>
          
    <Storyboard x:Name="Part_MouseDown"/>
          
    <Storyboard x:Name="Part_MouseUp"/>
          
    <Storyboard x:Name="Part_MouseLeave"/>
        
    </Grid.Resources>
        
    <Rectangle x:Name="Part_BackgroundRect"/>
        
    <TextBlock x:Name="Part_Caption"/>
        
    <Rectangle x:Name="Part_ForegroundRect"/>
        
    <Rectangle x:Name="Part_HighlightRect"/>
      
    </Grid>
    </ControlTemplate>

          从上面代码可以看出其采用控件模版的方式进行定义。但其鼠标在按钮上移入移出等状态的Storyboard
    (故事板)并未进行定义。而肯体的实现被放在了相应的子类(Button.xaml和RepeatButton.xaml)进行实现。
    下面就是其中的Button.xaml内容:

    <ControlTemplate xmlns="http://schemas.microsoft.com/client/2007"
                     xmlns:x
    ="http://schemas.microsoft.com/winfx/2006/xaml" >
      
    <Grid x:Name="Part_Root" MouseEnter="btnClearMouseEnter" MouseLeave="btnClearMouseLeave" 
              MouseLeftButtonDown
    ="btnClearMouseDown" MouseLeftButtonUp="btnClearMouseUp">
        
    <Grid.Resources>
          
    <Storyboard x:Name="Part_MouseEnter">
            
    <ColorAnimation Duration="00:00:00.25" To="#3DFFFFFF" Storyboard.TargetName="Part_HighlightRect" 
                       Storyboard.TargetProperty
    ="(Shape.Fill).(SolidColorBrush.Color)" />
          
    </Storyboard>
          
    <Storyboard x:Name="Part_MouseDown">
            
    <ColorAnimation Duration="00:00:00.2" To="#22000000" Storyboard.TargetName="Part_HighlightRect" 
                       Storyboard.TargetProperty
    ="(Shape.Fill).(SolidColorBrush.Color)" />
          
    </Storyboard>
          
    <Storyboard x:Name="Part_MouseUp">
            
    <ColorAnimation Duration="00:00:00.2" To="#3DFFFFFF" Storyboard.TargetName="Part_HighlightRect" 
                       Storyboard.TargetProperty
    ="(Shape.Fill).(SolidColorBrush.Color)" />
          
    </Storyboard>
          
    <Storyboard x:Name="Part_MouseLeave">
            
    <ColorAnimation Duration="00:00:00.25" To="#00FFFFFF" Storyboard.TargetName="Part_HighlightRect" 
                       Storyboard.TargetProperty
    ="(Shape.Fill).(SolidColorBrush.Color)" />
          
    </Storyboard>
        
    </Grid.Resources>
        
    <Rectangle x:Name="Part_BackgroundRect" StrokeThickness="4" RadiusX="16" RadiusY="36" Stroke="#46000000">
          
    <Rectangle.Fill>
            
    <LinearGradientBrush EndPoint="0.5,-0.4" StartPoint="0.5,1.4">
              
    <GradientStop Color="Gray" Offset="0.242"/>
              
    <GradientStop Color="DarkBlue" Offset="0.333"/>
            
    </LinearGradientBrush>
          
    </Rectangle.Fill>
        
    </Rectangle>
        
    <TextBlock x:Name="Part_Caption" VerticalAlignment="Center" HorizontalAlignment="Center" 
              Foreground
    ="Gold" Text="Button">
          
    <TextBlock.RenderTransform>
            
    <TranslateTransform X="0" Y="-2"/>
          
    </TextBlock.RenderTransform>
        
    </TextBlock>
        
    <Rectangle x:Name="Part_ForegroundRect" VerticalAlignment="Top" StrokeThickness="4" RadiusX="16" 
              RadiusY
    ="36" Width="124" Height="32">
          
    <Rectangle.Fill>
            
    <LinearGradientBrush EndPoint="0.5,-0.409" StartPoint="0.5,1.409">
              
    <GradientStop Color="#00FFFFFF" Offset="0.13"/>
              
    <GradientStop Color="#FFFFFFFF" Offset="1"/>
            
    </LinearGradientBrush>
          
    </Rectangle.Fill>
        
    </Rectangle>
        
    <Rectangle VerticalAlignment="Top" RadiusX="16" RadiusY="36" Fill="#00FFFFFF" x:Name="Part_HighlightRect"/>
      
    </Grid>
    </ControlTemplate>

       注:这样设计方式本人感觉很有意思,很有“面向对象”的味道,呵呵。
      
       下面简要浏览一下ButtonBase.xaml.cs的代码:

     

    [TemplatePart(Name = "Part_Root", Type = typeof(Panel))]
    [TemplatePart(Name 
    = "Part_Caption", Type = typeof(TextBlock))]
    [TemplatePart(Name 
    = "Part_ForegroundRect", Type = typeof(Rectangle))]
    [TemplatePart(Name 
    = "Part_BackgroundRect", Type = typeof(Rectangle))]
    [TemplatePart(Name 
    = "Part_HighlightRect", Type = typeof(Rectangle))]
    [TemplatePart(Name 
    = "Part_MouseEnter", Type = typeof(Storyboard))]
    [TemplatePart(Name 
    = "Part_MouseLeave", Type = typeof(Storyboard))]
    [TemplatePart(Name 
    = "Part_MouseDown", Type = typeof(Storyboard))]
    [TemplatePart(Name 
    = "Part_MouseUp", Type = typeof(Storyboard))]
    public abstract partial class ButtonBase : Control
    {
        
    /// <summary>
        
    /// 定义单击事件
        
    /// </summary>
        public event EventHandler Click;
        
    /// <summary>
        
    /// 执行单击事件的绑定方法
        
    /// </summary>
        protected void OnClick()
        {
            
    if (Click != null)
            {
                Click(
    thisnew EventArgs());
            }
        }

        
    /// <summary>
        
    /// 标题属性
        
    /// </summary>
        public string Caption
        {
            
    get { return this.Part_Caption.Text; }
            
    set { this.Part_Caption.Text = value; }
        }
        
    /// <summary>
        
    /// 鼠标移入控件区域时启动Part_MouseEnter故事板,下面类似
        
    /// </summary>
        
    /// <param name="sender"></param>
        
    /// <param name="e"></param>
        protected virtual void Part_Root_MouseEnter(object sender, MouseEventArgs e)
        {
            Part_MouseEnter.Begin();
        }

        
    protected virtual void Part_Root_MouseLeave(object sender, MouseEventArgs e)
        {
            Part_MouseLeave.Begin();
        }

        
    protected virtual void Part_Root_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            Part_MouseDown.Begin();
        }

        
    protected virtual void Part_Root_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            Part_MouseUp.Begin();
            
    //执行单击事件的绑定方法
            OnClick();
        }

        
    protected Storyboard Part_MouseEnter, Part_MouseDown, Part_MouseLeave, Part_MouseUp;
        
    protected Rectangle Part_ForegroundRect, Part_BackgroundRect, Part_HighlightRect;
        
    protected Panel Part_Root;
        
    protected TextBlock Part_Caption;
    }

      其实上面的代码与我们平时写.net控件类似,也是属性事件的定义。当然不同的地方就是对故事板的使用,
    而故事板会让我们的按钮在鼠标触发事件时在UI上看起来更酷。当然下面还要看一下相应的Button中的内容,因
    为这才是实际运行时使用的控件,其代码如下:

        

    public partial class Button : ButtonBase
        {
            
    public Button()
            {
                
    //加载Button.xaml中的内容,为下面获取元素进行相应操作
                string xaml = ResourceHelper.GetTemplate(this.GetType());
                ControlTemplate template 
    = (ControlTemplate)XamlReader.Load(xaml);
                
    this.Template = template;
                
    this.ApplyTemplate();
            }

            
    /// <summary>
            
    /// 对当前模板(xaml)中的元素进行(主要是鼠标)事件绑定
            
    /// </summary>
            public override void OnApplyTemplate()
            {
                Part_Root 
    = (Panel)GetTemplateChild("Part_Root");
                Part_Caption 
    = (TextBlock)GetTemplateChild("Part_Caption");
                Part_ForegroundRect 
    = (Rectangle)GetTemplateChild("Part_ForegroundRect");
                Part_BackgroundRect 
    = (Rectangle)GetTemplateChild("Part_BackgroundRect");
                Part_HighlightRect 
    = (Rectangle)GetTemplateChild("Part_HighlightRect");
                Part_MouseEnter 
    = (Storyboard)GetTemplateChild("Part_MouseEnter");
                Part_MouseLeave 
    = (Storyboard)GetTemplateChild("Part_MouseLeave");
                Part_MouseDown 
    = (Storyboard)GetTemplateChild("Part_MouseDown");
                Part_MouseUp 
    = (Storyboard)GetTemplateChild("Part_MouseUp");

                Part_Root.SizeChanged 
    += new SizeChangedEventHandler(Part_Root_SizeChanged);
                Part_Root.MouseEnter 
    += new MouseEventHandler(Part_Root_MouseEnter);
                Part_Root.MouseLeave 
    += new MouseEventHandler(Part_Root_MouseLeave);
                Part_Root.MouseLeftButtonDown 
    += new MouseButtonEventHandler(Part_Root_MouseLeftButtonDown);
                Part_Root.MouseLeftButtonUp 
    += new MouseButtonEventHandler(Part_Root_MouseLeftButtonUp);
            }

            
    /// <summary>
            
    /// 按钮的实际高度或宽度发生变化时的处理事件
            
    /// </summary>
            
    /// <param name="sender"></param>
            
    /// <param name="e"></param>
            void Part_Root_SizeChanged(object sender, SizeChangedEventArgs e)
            {
                Part_ForegroundRect.Width 
    = Part_Root.ActualWidth - 16d;
                Part_ForegroundRect.Height 
    = Part_Root.ActualHeight - 12d;
                Part_HighlightRect.Width 
    = Part_Root.ActualWidth - 10d;
                Part_HighlightRect.Height 
    = Part_Root.ActualHeight - 8d;
                
    if (Part_Root.ActualWidth > Part_Root.ActualHeight)
                {
                    Part_BackgroundRect.RadiusX 
    = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX = 
                                      Part_Root.ActualHeight 
    / 2d;
                    Part_BackgroundRect.RadiusY 
    = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY = 
                                      Part_Root.ActualWidth 
    / 4d;
                }
                
    else
                {
                    Part_BackgroundRect.RadiusX 
    = Part_ForegroundRect.RadiusX = Part_HighlightRect.RadiusX = 
                                      Part_Root.ActualHeight 
    / 4d;
                    Part_BackgroundRect.RadiusY 
    = Part_ForegroundRect.RadiusY = Part_HighlightRect.RadiusY = 
                                      Part_Root.ActualWidth 
    / 2d;
                }
            }
        }

        
        到这里还有另一个按钮控件RepeatButton没有介绍,其实它的内容也上面的Button代码相似,所以就不多介绍了。
    当然RepeatButton最终的用处是被放在了ImageSelector控件中做为子控制被加载,这其中与我们开发“复合型”控件
    相似。

      下面就是Button控制的运行效果,如下所示:


      


         当然这个DEMO在控件开发上还有一些有特色的地方,比如CheckBox控件等,我会在接下来的文章中加以说明,

    呵呵。

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

         tag:silverlight,button,imagesnipper

         作者:代震军,daizhj

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

         源码下载,请点击这里:)

      

         2010年4月整理的最新相册(vs2008):/Files/daizhj/ImageSnipper_new.rar

      

  • 相关阅读:
    linux kill命令以及 信号
    rhel7 系统服务——unit(单元)
    redis集群在线迁移
    二、主目录 Makefile 分析(3)
    二、主目录 Makefile 分析(2)
    二、主目录 Makefile 分析(1)
    一、文档目录分析
    Linux下解压缩
    设备树
    轮询
  • 原文地址:https://www.cnblogs.com/daizhj/p/1281204.html
Copyright © 2011-2022 走看看