posts - 283,  comments - 6275,  trackbacks - 107

     在前一阵子,我在网上找到了这个相册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

  

posted on 2008-09-05 09:49 代震军 阅读(4310) 评论(15) 编辑 收藏

FeedBack:
2008-09-05 10:14 | aaaa[未注册用户]
Sha Fa , Ding
 回复 引用   
2008-09-05 10:27 | 任力      
很不错的样子哦~~~
孩子好了,心也会平静不少吧,呵呵~~

 回复 引用 查看   
#3楼[楼主]
2008-09-05 10:40 | 代震军      
@任力
是呀,前些天郁闷+担心,搞得牙痛的“老毛病”又犯了。这两天宝宝和我都在吃药。

 回复 引用 查看   
2008-09-05 10:56 | chy710      
不错的说
 回复 引用 查看   
2008-09-05 11:23 | 簡簡單單..      
Mark
 回复 引用 查看   
#6楼[楼主]
2008-09-05 11:35 | 代震军      
@簡簡單單..
@chy710
:)

 回复 引用 查看   
2008-09-05 11:51 | yhb[未注册用户]
bill
 回复 引用   
2008-09-05 13:10 | 自由、创新、研究、探索……      
带孩子辛苦
 回复 引用 查看   
2008-09-05 17:06 | good man      
一边写代码一边代孩子
一边当爹一边当娘,
真幸福,呵呵
支持了哟

 回复 引用 查看   
#10楼[楼主]
2008-09-05 17:23 | 代震军      
@自由、创新、研究、探索……
@good man
呵呵:)

 回复 引用 查看   
2008-09-05 20:46 | 未登录的怪怪[未注册用户]
说句题外的,老兄把我这样还没成家的给吓住啦...
 回复 引用   
#12楼[楼主]
2008-09-08 09:27 | 代震军      
@未登录的怪怪
不会吧,我觉得你应该是那种天不怕地不怕的性格呀:)

 回复 引用 查看   
2009-02-28 20:27 | 峰![未注册用户]
我想请教您如何制作一个完整的silverlight的相册哦?您是用什么语言开发的呀?我很菜。。。呵呵。。。
 回复 引用   
#14楼[楼主]
2009-03-02 09:15 | 代震军      
@峰!
这相DEMO是c#写的,silverlight可用.net平台上的差不多任意一种语言来开发。关于相册应用的开发主要决绝对用户需求的定义了,比如想要什么功能,特色是什么等等

 回复 引用 查看   
2009-08-28 17:25 | 零末      
我下载了你的源码,出现了这样的错误: “System.Windows.Input.MouseButtonEventArgs”不包含“Source”的定义,并且找不到可接受类型为“System.Windows.Input.MouseButtonEventArgs”的第一个参数的扩展方法“Source”(是否缺少 using 指令或程序集引用?) D:\Download\ImageSnipper\ImageSnipperV2\Slider.xaml.cs 100 19 ImageSnipperV2
我不知道这是怎么回事。。
/// <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();
}
}
}
这部分是出错的地方

 回复 引用 查看   
昵称:代震军
园龄:5年11个月
荣誉:推荐博客
粉丝:492
关注:3

<2008年9月>
31123456
78910111213
14151617181920
21222324252627
2829301234
567891011

搜索

 
 

常用链接

随笔分类(366)

随笔档案(283)

文章分类(8)

文章档案(31)

相册

JavaScript

LINQ

silverlight

UML,OO

WebBlogger

负载开源项目

  • Discuz!NT
  • LLServer
  • TokyoTyrantClient
  • WebCam

个人简历

漫画

其它

企业级架构

网站案例研究

积分与排名

  • 积分 - 1217876
  • 排名 - 26

最新评论

阅读排行榜

评论排行榜

推荐排行榜