发布基于silverlight4的HaoRna.WebCam摄像头应用源码

      在去年年底,为了学习Silverlight4.0的新特性,我萌生了开发一个基于其新特性的项目。当然在这个项目中使用了包括鼠标右键菜单(Popup),打印功能(PrintDocument),导航功能摄像头,图片上传等。当然目前这个产品已在我们的官方产品Discuz!NT3.1中使用,今天开源的仅是本应用的源码。

      下面链接中是产品的运行截图:

      http://www.cnblogs.com/daizhj/archive/2010/02/26/1674389.html

 

      好了,接下来介绍一下产品的源码分布:

     

      其中:

      ChildWindows\
            CWMessageBox.xaml:显示窗口信息控件,用于显示系统提示的各种消息
            CWViewUploadedImage.xaml:显示用于上传头像或文件之后的显示结果(包括大中小三种尺寸)

      Controls\
            FocusRectangle.xaml: 焦点选择区域控件及相应用户拖动效果
            ImageButton.xaml:图片控件
            InkMenu.xaml:ink涂鸦工具栏控件

      Cursors\
            CustomCursors.xaml: 定制鼠标图标控件, 用于当鼠标进入FocusRectangle区域后显示定制的十字箭头

      Shader\三个silverlight滤镜

      Images\ 项目中使用的图标

      Utils\相关工具类
            Constants.cs,Converter.cs,UserFile.cs,FileCollection.cs, FileUploader.cs 图片上传代码
            Utils.cs 常用函数封装工具类

 

       AdvanceMode.xaml:高级模式的编辑窗口
       ImageBrowser.xaml:图片浏览和编辑上传窗口
       NavPage.xaml:导航窗口
       WebCam.xaml:摄像头功能和上传窗口

       

       好的,产品布局就介绍到这里了,下面是对于之前朋友感兴趣的一些功能的代码介绍。
       首先就是焦点选择框(矩形)的实现原理和相应代码,位于FocusRectangle.xaml和FocusRectangle.xaml.cs 原理就是首先绘制8个小矩形,作为用户进行鼠标操作的入口(均定制了鼠标点击操作代码),然后将这8个小矩形分布在一个大矩形的四角和两两节点间的中心位置,当然也加入鼠标的拖动和“上下左右扩展”代码,明确了实现方式之后,就看一下源码来加深一下理解了: 

      

      XAML:

<Canvas x:Name="LayoutRoot">       
   
<Canvas Name="ViewportHost" Height="270" Width="270" Background="Gray">
       
<ScrollViewer Canvas.ZIndex="0" Name="imageScroll" BorderThickness="0"  Background="Transparent" Width="270"  Height="270" VerticalScrollBarVisibility="Hidden" HorizontalScrollBarVisibility="Hidden">
           
<Rectangle Name="Viewport" Width="270" Height="270" Canvas.ZIndex="100">
               
<Rectangle.Fill>
                   
<ImageBrush>
                       
<ImageBrush.ImageSource>
                           
<BitmapImage x:Name="selectedImage" UriSource ="../Images/main.jpg"/>
                       
</ImageBrush.ImageSource>
                   
</ImageBrush>
               
</Rectangle.Fill>
           
</Rectangle>
       
</ScrollViewer>
       
<!--<TextBlock x:Name="msgBox" Width="269" Text="000" Foreground="Red" Height="100" Canvas.ZIndex="10000" />-->
       
<local:CustomCursors x:Name="customCursors" Visibility="Collapsed"></local:CustomCursors>
       
<Rectangle Name="FocusRect" Canvas.Left="5" Canvas.Top="5" Fill="Transparent"  Opacity="1" Stroke="White" StrokeThickness="1"  />
   
</Canvas>
</Canvas>

    
       XAML文件中包括一个ScrollViewer用于实现图片的缩放效果,CustomCursors用于鼠标移入焦点区域时显示焦点图标而不是鼠标沙漏。

       下面则是FocusRectangle.xaml.cs代码,包括8个小矩形的枚举标识:

#region 方形中八个点的相对位置
/// <summary>
/// 方形中八个点的相对位置
/// </summary>
enum HitDownSquare
{
    HDS_NONE = 0,
    
/// <summary>
    
/// 顶
    
/// </summary>
    HDS_TOP = 1,
    
/// <summary>
    
/// 右
    
/// </summary>
    HDS_RIGHT = 2,
    
/// <summary>
    
/// 底
    
/// </summary>
    HDS_BOTTOM = 3,
    
/// <summary>
    
/// 左
    
/// </summary>
    HDS_LEFT = 4,
    
/// <summary>
    
/// 左上
    
/// </summary>
    HDS_TOPLEFT = 5,
    
/// <summary>
    
/// 右上
    
/// </summary>
    HDS_TOPRIGHT = 6,
    
/// <summary>
    
/// 左下
    
/// </summary>
    HDS_BOTTOMLEFT = 7,
    
/// <summary>
    
/// 右下
    
/// </summary>
    HDS_BOTTOMRIGHT = 8
}
#endregion

 

    主要的控件类实体,实现各种相关鼠标操作事件和图形绘制事件代码(详见注释):


public partial class FocusRectangle : UserControl
{
    
#region 属性设置
    
/// <summary>
    
/// 8个允许调整控件大小的小正方形
    
/// </summary>
    Rectangle[] SmallRect = new Rectangle[8];
    
/// <summary>
    
/// 8个小正方形的大小
    
/// </summary>
    Size Square = new Size(66);
    
/// <summary>
    
/// 上一次鼠标点击的位置
    
/// </summary>
    Point prevLeftClick;
    
/// <summary>
    
/// 8个小正方形的填充色
    
/// </summary>
    Color color = Colors.White;
    
/// <summary>
    
/// 标识鼠标左键已被按下并且已开始移动
    
/// </summary>
    bool trackingMouseMove = false;
    
/// <summary>
    
/// 当前鼠标点击位置信息
    
/// </summary>
    HitDownSquare CurrHitPlace = new HitDownSquare();
    
#endregion

    
public FocusRectangle()
    {
        InitializeComponent();
        
this.Loaded += new RoutedEventHandler(FocusRectangle_Loaded);
    }
        
    
#region 初始化相应元素信息
    
/// <summary>
    
/// 初始化相应元素信息
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    void FocusRectangle_Loaded(object sender, RoutedEventArgs e)
    {  
        Viewport.MinHeight = Viewport.MinWidth = 16;
        Viewport.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + (ViewportHost.Height - Viewport.Height) / 2);
        Viewport.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + (ViewportHost.Width - Viewport.Width) / 2);

        
//初始设置FocusRect
        FocusRect.Width = FocusRect.Height = 100;
        FocusRect.MaxWidth = ViewportHost.Width;
        FocusRect.MaxHeight = ViewportHost.Height;
        FocusRect.MinHeight = FocusRect.MinWidth = 8;
        FocusRect.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + (ViewportHost.Height - FocusRect.Height) / 2);
        FocusRect.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + (ViewportHost.Width - FocusRect.Width) / 2);

        
#region 8个小正方形位置
        
//左上
        SmallRect[0= new Rectangle() { Name = "SmallRect0", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//上中间        
        SmallRect[4= new Rectangle() { Name = "SmallRect4", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//右上
        SmallRect[1= new Rectangle() { Name = "SmallRect1", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//左下
        SmallRect[2= new Rectangle() { Name = "SmallRect2", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//下中间
        SmallRect[5= new Rectangle() { Name = "SmallRect5", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//右下
        SmallRect[3= new Rectangle() { Name = "SmallRect3", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//左中间
        SmallRect[6= new Rectangle() { Name = "SmallRect6", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };
        
//右中间
        SmallRect[7= new Rectangle() { Name = "SmallRect7", Width = Square.Width, Height = Square.Height, Fill = new SolidColorBrush(color) };

        SetRectangles();
        
#endregion                       

        
#region 事件绑定
        
foreach (Rectangle smallRectangle in SmallRect)
        {
            smallRectangle.Fill = new SolidColorBrush(color);
            smallRectangle.MouseMove += new MouseEventHandler(smallRectangle_MouseMove);
            smallRectangle.MouseLeftButtonUp += new MouseButtonEventHandler(smallRectangle_MouseLeftButtonUp);
            smallRectangle.MouseLeftButtonDown += new MouseButtonEventHandler(smallRectangle_MouseLeftButtonDown);
            smallRectangle.MouseEnter += new MouseEventHandler(smallRectangle_MouseEnter);
            LayoutRoot.Children.Add(smallRectangle);
        }
        FocusRect.MouseMove += new MouseEventHandler(FocusRect_MouseMove);
        FocusRect.MouseLeftButtonDown += new MouseButtonEventHandler(FocusRect_MouseLeftButtonDown);
        FocusRect.MouseLeftButtonUp += new MouseButtonEventHandler(FocusRect_MouseLeftButtonUp);
        FocusRect.MouseEnter += new MouseEventHandler(FocusRect_MouseEnter);
        FocusRect.MouseLeave += new MouseEventHandler(FocusRect_MouseLeave);
        
#endregion
    }  
    
#endregion


    
#region FocusRect鼠标事件

    
void FocusRect_MouseLeave(object sender, MouseEventArgs e)
    {
        customCursors.Visibility = System.Windows.Visibility.Collapsed;
    }

    
void FocusRect_MouseEnter(object sender, MouseEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        element.Cursor = Cursors.None;
        customCursors.Visibility = System.Windows.Visibility.Visible;
        customCursors.SetPostion(e.GetPosition(LayoutRoot));       
    }

    
void FocusRect_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        trackingMouseMove = false;
        element.ReleaseMouseCapture();
        prevLeftClick.X = prevLeftClick.Y = 0;
        element.Cursor =  Cursors.None;

        
if (Viewport.Width < FocusRect.Width)
            FocusRect.Width = Viewport.Width;
        
if (Viewport.Height < FocusRect.Height)
            FocusRect.Height = Viewport.Height;

        AssureFocusRectMoveInZone(element.Name);
        SetRectangles();
    }

    
void FocusRect_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        prevLeftClick = e.GetPosition(element);
        trackingMouseMove = true;
        
if (null != element)
        {
            element.CaptureMouse();
            element.Cursor = Cursors.None;
        }
    }

    
/// <summary>
    
/// 计算并设置Scroll的偏移量
    
/// </summary>
    
/// <param name="offSetX">鼠标X轴移动的偏移量</param>
    
/// <param name="offSetY">鼠标Y轴移动的偏移量</param>
    void ComputeScrollOffSet(double offSetX, double offSetY)
    {
        
double FocusRectTop = (double)FocusRect.GetValue(Canvas.TopProperty);
        
double FocusRectLeft = (double)FocusRect.GetValue(Canvas.LeftProperty);
        
double ViewportHostTop = (double)ViewportHost.GetValue(Canvas.TopProperty);
        
double ViewportHostLeft = (double)ViewportHost.GetValue(Canvas.LeftProperty);
        
//msgBox.Text = "FocusRect.Height" + FocusRect.Height + "   ViewportHost.Height" + ViewportHost.Height;
        if (offSetY > 0 && (FocusRect.Height + 8< ViewportHost.Height && (ViewportHostTop + ViewportHost.Height) > (FocusRectTop + FocusRect.Height)) //鼠标向下且未出ViewportHost区域时
            imageScroll.ScrollToVerticalOffset(imageScroll.VerticalOffset + (offSetY / 2* (Viewport.Height / (ViewportHost.Height - FocusRectTop - FocusRect.Height)));

        
if (offSetY < 0 && (FocusRect.Height + 8< ViewportHost.Height && ViewportHostTop < FocusRectTop) //鼠标向上且未出ViewportHost区域时
            imageScroll.ScrollToVerticalOffset(imageScroll.VerticalOffset + (offSetY / 2* ((Viewport.Height / FocusRectTop)));

        
if (offSetX > 0 && (FocusRect.Width + 8< ViewportHost.Width && (ViewportHostLeft + ViewportHost.Width) > (FocusRectLeft + FocusRect.Width)) //鼠标向右且未出ViewportHost区域时
            imageScroll.ScrollToHorizontalOffset(imageScroll.HorizontalOffset + (offSetX /2* (Viewport.Width / (ViewportHost.Width - FocusRectLeft - FocusRect.Width)));

        
if (offSetX < 0 && (FocusRect.Width + 8< ViewportHost.Width && ViewportHostLeft < FocusRectLeft) //鼠标向左且未出ViewportHost区域时
            imageScroll.ScrollToHorizontalOffset(imageScroll.HorizontalOffset + (offSetX/2* ((Viewport.Width / FocusRectLeft)));

        
//msgBox.Text = imageScroll.HorizontalOffset.ToString();
    }

     
/// <summary>
    
/// FocusRect鼠标移动事件
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    void FocusRect_MouseMove(object sender, MouseEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        
if (element != null)
            element.Cursor = Cursors.None;

        
if (trackingMouseMove)
        {
            
double offSetX = e.GetPosition(element).X - prevLeftClick.X;
            
double offSetY = e.GetPosition(element).Y - prevLeftClick.Y;
     
            
if (((double)element.GetValue(Canvas.TopProperty) + offSetY) >=4 && (((double)FocusRect.GetValue(Canvas.TopProperty) + FocusRect.Height) + offSetY + 3<= ViewportHost.Height)
                element.SetValue(Canvas.TopProperty, (double)element.GetValue(Canvas.TopProperty) + offSetY);

            
if (((double)element.GetValue(Canvas.LeftProperty) + offSetX) >=4 && (((double)FocusRect.GetValue(Canvas.LeftProperty) + FocusRect.Width) + offSetX + 3<= ViewportHost.Width)
                element.SetValue(Canvas.LeftProperty, (double)element.GetValue(Canvas.LeftProperty) + offSetX);

            ComputeScrollOffSet(offSetX, offSetY);
            SetRectangles();
        }
        customCursors.SetPostion(e.GetPosition(LayoutRoot));         
    }
    
#endregion


    
#region 确保FocusRect在Viewport中进行移动和缩放
    
/// <summary>
    
/// 确保FocusRect在Viewport中进行缩放
    
/// </summary>
    public void AssureFocusRectZoomInZone(double zoom, double mininum)
    {
        
double ViewPortTop = (double)Viewport.GetValue(Canvas.TopProperty);
        
double ViewPortLeft = (double)Viewport.GetValue(Canvas.LeftProperty);
        
double FocusRectTop = (double)FocusRect.GetValue(Canvas.TopProperty);
        
double FocusRectLeft = (double)FocusRect.GetValue(Canvas.LeftProperty);

        
if (zoom == mininum)
        {
            FocusRect.SetValue(Canvas.LeftProperty, ViewPortLeft);
            FocusRect.Width = Viewport.Width;
        }
        
else
        {
            
//确保顶部不越界
            if (ViewPortTop > FocusRectTop)
                FocusRect.SetValue(Canvas.TopProperty, ViewPortTop);

            
//确保左侧不越界
            if (ViewPortLeft > FocusRectLeft)
                FocusRect.SetValue(Canvas.LeftProperty, ViewPortLeft);

            
//判断x是否右侧越界
            if ((Viewport.Width + ViewPortLeft) < (FocusRect.Width + FocusRectLeft))
            {
                
//如果已越界,但左侧未越界
                if (Viewport.Width > FocusRect.Width)
                    FocusRect.SetValue(Canvas.LeftProperty, ViewPortLeft + Viewport.Width - FocusRect.Width);
                
else
                    FocusRect.Width = Viewport.Width;
            }

            
//判断是否底部越界
            if ((Viewport.Height + ViewPortTop) < (FocusRect.Height + FocusRectTop))
            {
                
//如果已越界,但顶部未越界
                if (Viewport.Height > FocusRect.Height)
                    FocusRect.SetValue(Canvas.TopProperty, ViewPortTop + Viewport.Height - FocusRect.Height);
                
else
                    FocusRect.Height = Viewport.Height;
            }
        }
        SetRectangles();
    }
   
    
/// <summary>
    
/// FocusRect是否在Viewport中,如不在,则确保其不超出Viewport区域
    
/// </summary>
    
/// <returns></returns>
    bool AssureFocusRectMoveInZone(string elementName)
    {
        
bool result = true;
        
//try
        
//{
            double ViewPortTop = (double)Viewport.GetValue(Canvas.TopProperty);
            
double ViewPortLeft = (double)Viewport.GetValue(Canvas.LeftProperty);
            
double FocusRectTop = (double)FocusRect.GetValue(Canvas.TopProperty);
            
double FocusRectLeft = (double)FocusRect.GetValue(Canvas.LeftProperty);
        
            
if (Viewport.Height > ViewportHost.Height)//已使用放大功能,向上拖动
            {
                
if (0 > FocusRectTop)
                {
                    FocusRect.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + 4);
                    result = false;
                }
            }
            
else
            {
                
if (ViewPortTop > FocusRectTop)
                {
                    FocusRect.SetValue(Canvas.TopProperty, ViewPortTop);
                    result = false;
                }
            }

            
if (Viewport.Width >= ViewportHost.Width)//已使用放大功能,向左拖动
            {
                
if (0 > FocusRectLeft)
                {
                    FocusRect.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + 4);
                    result = false;
                }
            }
            
else
            {
                
if (ViewPortLeft > FocusRectLeft)
                {
                    FocusRect.SetValue(Canvas.LeftProperty, ViewPortLeft);
                    result = false;
                }
            }

            
if (Viewport.Width >= ViewportHost.Width)//已使用放大功能,向右拖动
            {
                
if ((ViewportHost.Width) < (FocusRect.Width + FocusRectLeft))
                {
                    
if (elementName == "FocusRect")
                        FocusRect.SetValue(Canvas.LeftProperty, ViewportHost.Width - FocusRect.Width - 4);
                    
else
                    {
                        FocusRect.Width = ViewportHost.Width - FocusRectLeft - 4;
                    }
                    result = false;
                }
            }
            
else
            {
                
if ((Viewport.Width + ViewPortLeft) < (FocusRect.Width + FocusRectLeft))
                {
                    
if (elementName == "FocusRect")
                        FocusRect.SetValue(Canvas.LeftProperty, ViewPortLeft + Viewport.Width - FocusRect.Width);
                    
else
                        FocusRect.Width = ViewPortLeft + Viewport.Width - FocusRectLeft;
                    result = false;
                }
            }

            
if (Viewport.Height > ViewportHost.Height)//已使用放大功能,向下拖动
            {
                
if ((ViewportHost.Height) < (FocusRect.Height + FocusRectTop))
                {
                    
if (elementName == "FocusRect")
                        FocusRect.SetValue(Canvas.TopProperty, ViewportHost.Height - FocusRect.Height - 4);
                    
else
                        FocusRect.Height = ViewportHost.Height - FocusRectTop - 4;
                    result = false;
                }
            }
            
else
            {
                
if ((Viewport.Height + ViewPortTop) < (FocusRect.Height + FocusRectTop))
                {
                    
if (elementName == "FocusRect")
                        FocusRect.SetValue(Canvas.TopProperty, ViewPortTop + Viewport.Height - FocusRect.Height);
                    
else
                        FocusRect.Height = ViewPortTop + Viewport.Height - FocusRectTop;
                    result = false;
                }
            }
            
        
//}
        
//catch
        
//{
        
//    result = false;
        
//}
        return result;
    }

    
#endregion


    
#region smallRectangle 鼠标事件

    
void smallRectangle_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        trackingMouseMove = false;
        element.ReleaseMouseCapture();
        prevLeftClick.X = prevLeftClick.Y = 0;
        element.Cursor = null;

        
if (Viewport.Width < FocusRect.Width)
            FocusRect.Width = Viewport.Width;
        
if (Viewport.Height < FocusRect.Height)
            FocusRect.Height = Viewport.Height;

        AssureFocusRectMoveInZone(element.Name);
        SetRectangles();
    }

    
/// <summary>
    
/// 鼠标按下事件
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    void smallRectangle_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        prevLeftClick = e.GetPosition(element);
        trackingMouseMove = true;
        
if (null != element)
        {
            element.CaptureMouse();
            element.Cursor = Cursors.Hand;
        }
    }

    
/// <summary>
    
/// SmallRect[]鼠标移动事件
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    void smallRectangle_MouseMove(object sender, MouseEventArgs e)
    {
        
if (trackingMouseMove)
        {
            FrameworkElement element = sender as FrameworkElement;
            
double offSetY = e.GetPosition(element).Y - prevLeftClick.Y;
            
double offSetX = e.GetPosition(element).X - prevLeftClick.X;

            
if (AssureFocusRectMoveInZone(element.Name))
            {
                
switch (this.CurrHitPlace)
                {
                    
case HitDownSquare.HDS_TOP:
                        
if ((FocusRect.Height - offSetY) > 4)
                        {
                            FocusRect.Height = FocusRect.Height - offSetY;
                            
if (FocusRect.Height > 4)
                                FocusRect.SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + offSetY);
                        }
                        
break;
                    
case HitDownSquare.HDS_TOPLEFT:
                        
if ((FocusRect.Height - offSetY) > 4)
                        {
                            FocusRect.Height = FocusRect.Height - offSetY;
                            
if (FocusRect.Height > 4)
                                FocusRect.SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + offSetY);
                        }
                        
if ((FocusRect.Width - offSetX) > 4)
                        {
                            FocusRect.Width = FocusRect.Width - offSetX;
                            
if (FocusRect.Width > 4)
                                FocusRect.SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + offSetX);
                        }
                        
break;
                    
case HitDownSquare.HDS_TOPRIGHT:
                        
if ((FocusRect.Height - offSetY) >4)
                        {
                            FocusRect.Height = FocusRect.Height - offSetY;
                            
if (FocusRect.Height > 4)
                                FocusRect.SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + offSetY);
                        }
                        
if ((FocusRect.Width + offSetX) > 4)
                            FocusRect.Width = FocusRect.Width + offSetX;
                        
break;
                    
case HitDownSquare.HDS_RIGHT:
                        
if ((FocusRect.Width + offSetX) > 4)
                            FocusRect.Width = FocusRect.Width + offSetX;
                        
break;
                    
case HitDownSquare.HDS_BOTTOM:
                        
if ((FocusRect.Height + offSetY) > 4)
                            FocusRect.Height = FocusRect.Height + offSetY;
                        
break;
                    
case HitDownSquare.HDS_BOTTOMLEFT:
                        
if ((FocusRect.Height + offSetY) > 4)
                            FocusRect.Height = FocusRect.Height + offSetY;
                        
if ((FocusRect.Width - offSetX) > 4)
                        {
                            FocusRect.Width = FocusRect.Width - offSetX;
                            
if (FocusRect.Width > 4)
                                FocusRect.SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + offSetX);
                        }
                        
break;
                    
case HitDownSquare.HDS_BOTTOMRIGHT:
                        
if ((FocusRect.Height + offSetY) > 4)
                            FocusRect.Height = FocusRect.Height + offSetY;
                        
if ((FocusRect.Width + offSetX) >4)
                            FocusRect.Width = FocusRect.Width + offSetX;
                        
break;
                    
case HitDownSquare.HDS_LEFT:
                        
if ((FocusRect.Width - offSetX) > 4)
                        {
                            FocusRect.Width = FocusRect.Width - offSetX;
                            
if (FocusRect.Width > 4)
                                FocusRect.SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + offSetX);
                        }
                        
break;
                    
case HitDownSquare.HDS_NONE:
                        FocusRect.SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + offSetX);
                        FocusRect.SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + offSetY);
                        
break;
                }                   
            }
            SetRectangles();
        }
    }
    
#endregion


    
#region 设置8个小正方形位置
    
/// <summary>
    
/// 设置8个小正方形位置
    
/// </summary>
    public void SetRectangles()
    {
        
//msgBox.Text = "FocusRect height: " + FocusRect.Height + "  Width:" + FocusRect.Width + " Top:" + FocusRect.GetValue(Canvas.TopProperty) + " Left:" + FocusRect.GetValue(Canvas.LeftProperty);
        
//左上
        SmallRect[0].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) - Square.Width / 2);
        SmallRect[0].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) - Square.Height / 2);
        
//上中间           
        SmallRect[4].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + (FocusRect.Width - Square.Width)/2);
        SmallRect[4].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) - Square.Height/2);
        
//右上        
        SmallRect[1].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + FocusRect.Width - Square.Width/2);
        SmallRect[1].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) - Square.Height / 2);
        
//左下           
        SmallRect[2].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) - Square.Width / 2);
        SmallRect[2].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + FocusRect.Height - Square.Height / 2);
        
//下中间
        SmallRect[5].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + (FocusRect.Width - Square.Width) / 2);
        SmallRect[5].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + FocusRect.Height - Square.Height / 2);
        
//右下
        SmallRect[3].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + FocusRect.Width - Square.Height / 2);
        SmallRect[3].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + FocusRect.Height - Square.Height / 2);
        
//左中间
        SmallRect[6].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) - Square.Width / 2);
        SmallRect[6].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + (FocusRect.Height - Square.Height) / 2);
        
//右中间
        SmallRect[7].SetValue(Canvas.LeftProperty, (double)FocusRect.GetValue(Canvas.LeftProperty) + FocusRect.Width - Square.Width / 2);
        SmallRect[7].SetValue(Canvas.TopProperty, (double)FocusRect.GetValue(Canvas.TopProperty) + (FocusRect.Height - Square.Height) / 2);
    }
    
#endregion


    
#region 设置鼠标Cursor和相应位置CurrHitPlace
    
void smallRectangle_MouseEnter(object sender, MouseEventArgs e)
    {
        FrameworkElement element = sender as FrameworkElement;
        Hit_Test(element, e.GetPosition(null));
    }

    
/// <summary>
    
/// 设置鼠标Cursor和相应位置CurrHitPlace
    
/// </summary>
    
/// <param name="element"></param>
    
/// <param name="point"></param>
    
/// <returns></returns>
    public bool Hit_Test(FrameworkElement element, Point point)
    {
        
switch (element.Name)
        {
            
case "SmallRect0":
                {
                    element.Cursor = Cursors.Hand; //.SizeNWSE;
                    CurrHitPlace = HitDownSquare.HDS_TOPLEFT;
                    
break;
                }
            
case "SmallRect3":
                {
                    element.Cursor = Cursors.Hand;//  .SizeNWSE;
                    CurrHitPlace = HitDownSquare.HDS_BOTTOMRIGHT;
                    
break;
                }
            
case "SmallRect1":
                {
                    element.Cursor = Cursors.Hand;//  .SizeNESW;
                    CurrHitPlace = HitDownSquare.HDS_TOPRIGHT;
                    
break;
                }
            
case "SmallRect2":
                {
                    element.Cursor = Cursors.Hand;//  .SizeNESW;
                    CurrHitPlace = HitDownSquare.HDS_BOTTOMLEFT;
                    
break;
                }
            
case "SmallRect4":
                {
                    element.Cursor = Cursors.SizeNS;
                    CurrHitPlace = HitDownSquare.HDS_TOP;
                    
break;
                }
            
case "SmallRect5":
                {
                    element.Cursor = Cursors.SizeNS;
                    CurrHitPlace = HitDownSquare.HDS_BOTTOM;
                    
break;
                }
            
case "SmallRect6":
                {
                    element.Cursor = Cursors.SizeWE;
                    CurrHitPlace = HitDownSquare.HDS_LEFT;
                    
break;
                }
            
case "SmallRect7":
                {
                    element.Cursor = Cursors.SizeWE;
                    CurrHitPlace = HitDownSquare.HDS_RIGHT;
                    
break;
                }
            
default:
                {
                    FocusRect.Cursor = Cursors.Arrow;
                    CurrHitPlace = HitDownSquare.HDS_NONE;
                    
break;
                }
        }
        
return true;
    }
   
#endregion


    
#region 滑动条事件处理代码
    
/// <summary>
    
/// 滑动条事件处理代码
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    public void ViewportSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
    {
        Slider ZoomInOut = sender as Slider;
        
if (ZoomInOut.Value >= ZoomInOut.Minimum && imageRatio * ZoomInOut.Value >= ZoomInOut.Minimum)
        {
            Viewport.Width = ZoomInOut.Value;
            Viewport.Height = imageRatio * ZoomInOut.Value;
            Viewport.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + (ViewportHost.Width - Viewport.Height) / 2);
            Viewport.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + (ViewportHost.Width - Viewport.Width) / 2);
            AssureFocusRectZoomInZone(ZoomInOut.Value, ZoomInOut.Minimum);
        }
    }
    
#endregion


    
#region 加载图片流信息并设置宽高比例
    
/// <summary>
    
/// 图片的高宽比
    
/// </summary>
    private double imageRatio = 1;

    
/// <summary>
    
/// 加载图片文件信息
    
/// </summary>
    
/// <param name="fileStream"></param>
    public void LoadImageStream(FileStream fileStream, Slider zoomInOut)
    {
        
double width = ViewportHost.Width, height = ViewportHost.Height;
        
//hack:获取相应的图片高宽信息
        BitmapImage bitmapImage = new BitmapImage();
        bitmapImage.SetSource(fileStream);
        zoomInOut.Maximum = bitmapImage.PixelWidth;

        
#region 用获取的图片高宽初始化Viewport,FocusRect区域和以slider
        
if (bitmapImage.PixelWidth < bitmapImage.PixelHeight)//当图片宽小于高时
        {
            
if (bitmapImage.PixelWidth > width) //当图片宽度超过可视区域的宽度时
            {
                height = ((double)width / bitmapImage.PixelWidth) * bitmapImage.PixelHeight;
                
//zoomInOut.Value = (double)width / bitmapImage.PixelWidth;
            }
            
else //未超过时则使用图片的高宽初始化显示区域
            {
                width = bitmapImage.PixelWidth;
                height = bitmapImage.PixelHeight;
            }
        }
        
else//当图片高小于宽时
        {
            
if (bitmapImage.PixelHeight > height)//当图片高度超过可视区域的高度时
            {
                width = ((double)height / bitmapImage.PixelHeight) * bitmapImage.PixelWidth;
                
//zoomInOut.Value = (double)height / bitmapImage.PixelHeight;
            }
            
else//未超过时则使用图片的高宽初始化显示区域
            {
                width = bitmapImage.PixelWidth;
                height = bitmapImage.PixelHeight;
            }
        }

        Viewport.Width = zoomInOut.Value = width;
        Viewport.Height = height;
        Viewport.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + (ViewportHost.Height - Viewport.Height) / 2);
        Viewport.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + (ViewportHost.Width - Viewport.Width) / 2);

        FocusRect.Width = width >= 100 ? 100 : width;
        FocusRect.Height = height >= 100 ? 100 : height;
        FocusRect.SetValue(Canvas.TopProperty, (double)ViewportHost.GetValue(Canvas.TopProperty) + (ViewportHost.Height - FocusRect.Height) / 2);
        FocusRect.SetValue(Canvas.LeftProperty, (double)ViewportHost.GetValue(Canvas.LeftProperty) + (ViewportHost.Width - FocusRect.Width) / 2);

        zoomInOut.Minimum = 16;
        zoomInOut.ValueChanged += new RoutedPropertyChangedEventHandler<double>(ViewportSlider_ValueChanged);
        imageRatio = (double)bitmapImage.PixelHeight / bitmapImage.PixelWidth;

        SetRectangles();
        
#endregion

        selectedImage.SetSource(fileStream);
    }
    
#endregion
}

 

     下面是鼠标右键菜单代码(位于ChildWindows\CWViewUploadedImage.xaml),采取动态加载控件方式来加载菜单项并绑定相应事件(如打印):


/// <summary>
/// 初始化右键菜单
/// </summary>
void InitPopMenu()
{
    Border border = new Border()
    {
        BorderBrush = new SolidColorBrush(Color.FromArgb(255167171176)),
        CornerRadius = new CornerRadius(2),
        BorderThickness = new Thickness(1),
        Background = new SolidColorBrush(Colors.White),
        Effect = new DropShadowEffect() { BlurRadius = 3, Color = Color.FromArgb(255230227236) }
    };

    StackPanel stackPanel = new StackPanel() { Orientation = Orientation.Vertical };
    stackPanel.Children.Insert(0, AddMenuItem("打印头像""images/print.png", PrintButton_Click));
    stackPanel.Children.Insert(1, AddMenuItem("保存到本地""images/save.png", DownLoadAvatar_Click));

    border.Child = stackPanel;
    popMenu.Child = border;
}

   
    下面就是菜单项的样式绑定代码:


/// <summary>
/// 加载菜单项
/// </summary>
/// <param name="menuName">菜单名称</param>
/// <param name="imageUrl">图片</param>
/// <param name="eventHandler">处理事件</param>
/// <returns></returns>
Grid AddMenuItem(string menuName, string imageUrl, RoutedEventHandler eventHandler)
{
    Grid grid = new Grid();// { Margin = new Thickness(1) };
    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(25) });
    grid.ColumnDefinitions.Add(new ColumnDefinition() { Width = new GridLength(80) });
    grid.Children.Add(new Rectangle() { Fill = new SolidColorBrush(Color.FromArgb(255233238238)) });
    grid.Children.Add(new Rectangle() { Fill = new SolidColorBrush(Color.FromArgb(255226228231)), HorizontalAlignment = HorizontalAlignment.Right, Width = 1 });

    Button roButton = new Button()
    {
        Height = 22,
        Margin = new Thickness(0000),
        HorizontalAlignment = HorizontalAlignment.Stretch,
        VerticalAlignment = VerticalAlignment.Top,
        HorizontalContentAlignment = HorizontalAlignment.Left,
        Style = Application.Current.Resources["ContextMenuButton"as Style
    };
    roButton.Click += eventHandler;

    Grid.SetColumnSpan(roButton, 2);
    StackPanel sp = new StackPanel() { Orientation = Orientation.Horizontal };
    Image roImage = new Image() { HorizontalAlignment = HorizontalAlignment.Left, Width = 16, Height = 16, Margin = new Thickness(1000) };
    roImage.Source = new BitmapImage(new Uri("/HaoRan.WebCam;component/" + imageUrl, UriKind.RelativeOrAbsolute));
    sp.Children.Add(roImage);
    sp.Children.Add(new TextBlock() { HorizontalAlignment = HorizontalAlignment.Left, Margin = new Thickness(16000), Text = menuName });

    roButton.Content = sp;
    grid.Children.Add(roButton);
    
return grid;
}


    接下来就是用户选择下载或打印的实现代码(里面的JpegHelper类是一个将WriteableBitmap转为jpeg图片的辅助类):

 

/// <summary>
 
/// 保存到本地
 
/// </summary>
 private void DownLoadAvatar_Click(object sender, RoutedEventArgs e)
 {
     
if (saveFileDlg.ShowDialog().Value)
     {
         
using (Stream dstStream = saveFileDlg.OpenFile())
         {
             
try
             {
                 Image image;
                 
double Size = FocusWidth > FocusHeight ? FocusWidth : FocusHeight;//hack:将高宽转为size,这样就可以将ui元素中的内容保存到本地了

                 
if (popMenu.Tag.ToString() == "LargeImageScrollViewer")
                     image = new Image() { Width = Size, Height = Size, Source = LargeImage.Source };
                 
else if (popMenu.Tag.ToString() == "MediumImageScrollViewer")
                     image = new Image() { Width = Size * 0.8, Height = Size * 0.8, Source = MediumImage.Source };
                 
else
                     image = new Image() { Width = Size * 0.6, Height = Size * 0.6, Source = SmallImage.Source };

                 WriteableBitmap bmp = new WriteableBitmap(image, null);
                 JpegHelper.EncodeJpeg(bmp, dstStream);
             }
             
catch (Exception ex)
             {
                 Utils.ShowMessageBox("Error saving snapshot", ex.Message);
             }
         }
     }
 }

 

     下面是打印代码:


#region 打印代码
 
/// <summary>
 
/// 点击打印按钮事件
 
/// </summary>
 
/// <param name="sender"></param>
 
/// <param name="e"></param>
 private void PrintButton_Click(object sender, RoutedEventArgs e)
 {
     PrintDocument doc = new PrintDocument() {};
     
//doc.StartPrint += new EventHandler<StartPrintEventArgs>(doc_StartPrint);
     doc.EndPrint += OnEndPrint;
     doc.PrintPage += new EventHandler<PrintPageEventArgs>(doc_PrintPage);
     doc.Print("打印头像");
 }

 
/// <summary>
 
/// 打印处理代码
 
/// </summary>
 
/// <param name="sender"></param>
 
/// <param name="e"></param>
 void doc_PrintPage(object sender, PrintPageEventArgs e)
 {
     PrintImage.Height = FocusHeight;
     PrintImage.Width = FocusWidth;
     
if (popMenu.Tag.ToString() == "MediumImageScrollViewer")
     {
         PrintImage.Height *= 0.8;
         PrintImage.Width *= 0.8;
     }
     
else if (popMenu.Tag.ToString() == "SmallImageScrollViewer")
     {
         PrintImage.Height *= 0.6;
         PrintImage.Width *= 0.6;
     }

     ImageInf.Text = "头像类型:" + popMenu.Tag.ToString().Replace("ScrollViewer"""+ "  宽:" + PrintImage.Width + "px  高:" + PrintImage.Height + "px";
     AppInf.Text = "Product Details: HaoRan.WebCam Beta2";
     PrintArea.Width = e.PrintableArea.Width;
     PrintArea.Height = e.PrintableArea.Height;
   
     e.PageVisual = PrintArea;
     
// 指定是否再次调用另一个页
     e.HasMorePages = false;
 }

 Action<Exception> completedCallback = (ex) =>
 {
     
if (ex != null)
     {
         Utils.ShowMessageBox("打印错误", ex.Message);
     }
 };

 
/// <summary>
 
/// 打印结束事件
 
/// </summary>
 
/// <param name="sender"></param>
 
/// <param name="e"></param>
 void OnEndPrint(object sender, EndPrintEventArgs e)
 {
     
if (completedCallback != null)
     {
         completedCallback(e.Error);
     }
 }


 
void pd_PrintPage(object sender, PrintPageEventArgs e)
 {
     
throw new NotImplementedException();
 }
 
#endregion

    
     下面是使用Silverlight4摄像头的代码(WebCam.xaml.cs):


/// <summary>
/// WebCam页
/// </summary>
public partial class WebCam : Page
{
    
/// <summary>
    
/// 初始化视频捕捉设备
    
/// </summary>
    private CaptureSource captureSource = new CaptureSource()
    {
        VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(),
        AudioCaptureDevice = CaptureDeviceConfiguration.GetDefaultAudioCaptureDevice()
    };
    
/// <summary>
    
/// 保存文件对话框
    
/// </summary>
    private SaveFileDialog saveFileDlg = new SaveFileDialog
    {
        DefaultExt = ".jpg",
        Filter = "JPEG Images (*jpeg *.jpg)|*.jpeg;*.jpg",
    };

    
public WebCam()
    {
        InitializeComponent();
        
this.Loaded += new RoutedEventHandler(WebCam_Loaded);
    }

    
void WebCam_Loaded(object sender, RoutedEventArgs e)
    {
        BtnUploadImage.IsEnabled = BtnAdvanceMode.IsEnabled = false;
        BtnCapture.IsEnabled = goBack.IsEnabled = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice() != null;     
    }

    
protected override void OnNavigatedTo(NavigationEventArgs e)
    {}
         
    
/// <summary>
    
/// 捕捉图像信息
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    private void BtnCapture_Click(object sender, RoutedEventArgs e)
    {
        
try
        {   // 开始捕捉            
            if (captureSource.State != CaptureState.Started)
            {
                captureSource.Stop();
                
// 创建 video brush 并填充到 rectangle
                VideoBrush vidBrush = new VideoBrush();
                vidBrush.Stretch = Stretch.UniformToFill;
                vidBrush.SetSource(captureSource);
                focusRectangle.Viewport.Fill = vidBrush;              

                
// 询问是否接入
                if (CaptureDeviceConfiguration.AllowedDeviceAccess || CaptureDeviceConfiguration.RequestDeviceAccess())
                {
                    focusRectangle.Viewport.MaxHeight = focusRectangle.Viewport.MaxWidth = ZoomInOut.Maximum = 400;
                    ZoomInOut.Value = 270;
                    ZoomInOut.Minimum = 16;
                    ZoomInOut.ValueChanged += new RoutedPropertyChangedEventHandler<double>(focusRectangle.ViewportSlider_ValueChanged);
                    captureSource.Start();

                    BtnCapture.Text = "打开摄像头";
                    BtnUploadImage.IsEnabled = BtnAdvanceMode.IsEnabled = true;
                }                   
            }
            
else
            {
                captureSource.Stop();
                BtnCapture.Text = "关闭摄像头";
                BtnUploadImage.IsEnabled = BtnAdvanceMode.IsEnabled = false;
            }
        }
        
catch (Exception ex)
        {
            Utils.ShowMessageBox("Error using webcam", ex.Message);
        }
    }

    
/// <summary>
    
/// 上传头像
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    private void BtnUploadImage_Click(object sender, RoutedEventArgs e)
    {
        captureSource.Stop();

        Utils.UploadUserFile(Utils.GetUserId() + ".jpg", focusRectangle.imageScroll, focusRectangle.FocusRect,
            
//定制UserFile的PropertyChanged 属性,如BytesUploaded,Percentage,IsDeleted
            new System.ComponentModel.PropertyChangedEventHandler(FileRowControl_PropertyChanged));       
    }

    
/// <summary>
    
/// 上传文件进度属性事件
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    void FileRowControl_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
    {
        UserFile userFile = sender as UserFile;
        
if (e.PropertyName == "Percentage")
        {
            Percentage.Value = userFile.Percentage;
            Percentage.Visibility = Percentage.Value == 100 ? Visibility.Collapsed : Visibility.Visible;
        }
        
//当前文件上传完毕
        if (userFile.State == Constants.FileStates.Finished)
        {
            CWViewUploadedImage cw = new CWViewUploadedImage();
            cw.Closed += (o, eventArgs) =>
            {
                
if (cw.DialogResult == true)//确定并就隐藏当前sl应用窗口
                    NavPage.javaScriptableObject.OnCloseAvatar(null); //调用js端注册事件
                
//Utils.ShowMessageBox("op: 确定并就隐藏当前sl应用窗口");
            };

            cw.LargeImageWidth.Text = focusRectangle.FocusRect.Width.ToString();
            cw.LargeImageHeight.Text = focusRectangle.FocusRect.Height.ToString().ToString();
            cw.Show();

            captureSource.Start();
        }
    }

    
/// <summary>
    
/// 返回上一页
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    private void goBack_Click(object sender, RoutedEventArgs e)
    {
        
this.NavigationService.GoBack();
    }

    
#region 高级模式事件代码
    
/// <summary>
    
/// 高级模式事件代码
    
/// </summary>
    
/// <param name="sender"></param>
    
/// <param name="e"></param>
    private void BtnAdvanceMode_Click(object sender, RoutedEventArgs e)
    {
        captureSource.Stop();

        Utils.UploadUserFile(Utils.GetUserId() + ".jpg", focusRectangle.imageScroll, focusRectangle.FocusRect,
            (o, eventArgs) => //定制UserFile的PropertyChanged 属性,如BytesUploaded,Percentage,IsDeleted
            {
                UserFile userFile = o as UserFile;
                
if (eventArgs.PropertyName == "Percentage")
                {
                    Percentage.Value = userFile.Percentage;
                    Percentage.Visibility = Percentage.Value == 100 ? Visibility.Collapsed : Visibility.Visible;
                }
                
//当前文件上传完毕
                if (userFile.State == Constants.FileStates.Finished)
                    
this.NavigationService.Navigate(
                         
new Uri(
                                    
string.Format("/AdvanceMode?focusWidth={0}&focusHeight={1}&fileName={2}",
                                    focusRectangle.FocusRect.Width,
                                    focusRectangle.FocusRect.Height,
                                    userFile.FileName),
                                UriKind.Relative));
            });
    }
    
#endregion
}



    下面是涂鸦功能中的工具栏XMAL和实现代码,如下图:
        

     InkMenu.xaml:

<Canvas x:Name="LayoutRoot" Background="AliceBlue">
    
<!--InkPresenter Start-->
    
<StackPanel Margin="0,0,8,0" Canvas.Top="5">          
        
<TextBlock FontSize="12"  Name="stroke">边框色:</TextBlock>
        
<Slider Name="inkStrokeSlider" Minimum="0" Maximum="1"  Width="100" Height="20" HorizontalAlignment="Left" Orientation="Horizontal" ValueChanged="inkStrokeSlider_ValueChanged">
            
<Slider.Background>
                
<LinearGradientBrush 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>
            
</Slider.Background>
        
</Slider>

        
<TextBlock FontSize="12" >填充色:</TextBlock>
        
<Slider Name="inkFillSlider" Minimum="0" Maximum="1"  Width="100" Height="20" HorizontalAlignment="Left"  Orientation="Horizontal" ValueChanged="inkFillSlider_ValueChanged">
            
<Slider.Background>
                
<LinearGradientBrush 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>
            
</Slider.Background>
        
</Slider>
        
<TextBlock FontSize="12" >边框:</TextBlock>
        
<Slider Name="inkThicknessSlider" Minimum="0" Maximum="1"  Width="100" Height="20" HorizontalAlignment="Left"  Orientation="Horizontal" ValueChanged="inkThicknessSlider_ValueChanged" />

        
<TextBlock FontSize="12" >透明:</TextBlock>
        
<Slider Name="inkTransparencySlider" Minimum="0" Maximum="1"  Width="100" Height="20" HorizontalAlignment="Left" Orientation="Horizontal" ValueChanged="inkTransparencySlider_ValueChanged" />

        
<TextBlock Canvas.Left="10" Canvas.Top="200" FontSize="12" >预览:</TextBlock>
        
<InkPresenter x:Name="inkPreview" Canvas.Top="215" Canvas.Left="15" Width="100" Height="35">
            
<InkPresenter.Background>
                
<LinearGradientBrush StartPoint="0,0" EndPoint="1,0">
                    
<GradientStop Color="Gray" Offset="0"/>
                    
<GradientStop Color="Snow" Offset="1"/>
                
</LinearGradientBrush>
            
</InkPresenter.Background>
            
<InkPresenter.Strokes>
                
<StrokeCollection>
                    
<Stroke>
                        
<Stroke.DrawingAttributes>
                            
<DrawingAttributes Color="Black" OutlineColor="Black" Height="5" Width="5"/>
                        
</Stroke.DrawingAttributes>
                        
<Stroke.StylusPoints>
                            
<StylusPointCollection>
                                
<StylusPoint X="6.365068435668945" Y="13.124124526977539"/>
                                
<StylusPoint X="6.365068435668945" Y="13.124124526977539" />
                                
<StylusPoint X="6.414070129394531" Y="13.76108169555664" />
                                
<StylusPoint X="6.414070129394531" Y="13.76108169555664" />
                                
<StylusPoint X="7.002099990844727" Y="14.153057098388671" />
                                
<StylusPoint X="7.590129852294922" Y="14.104059219360351" />
                                
<StylusPoint X="8.423171997070312" Y="13.859075546264648" />
                                
<StylusPoint X="9.501224517822265" Y="13.46710205078125" />
                                
<StylusPoint X="10.922296524047851" Y="12.830144882202148" />
                                
<StylusPoint X="12.58837890625" Y="12.046195983886718" />
                                
<StylusPoint X="14.401470184326171" Y="11.017265319824218" />
                                
<StylusPoint X="16.41057014465332" Y="10.037330627441406" />
                                
<StylusPoint X="18.41967010498047" Y="8.910406112670898" />
                                
<StylusPoint X="20.526775360107422" Y="7.73448371887207" />
                                
<StylusPoint X="22.437870025634765" Y="6.70555305480957" />
                                
<StylusPoint X="24.299964904785156" Y="5.725618362426758" />
                                
<StylusPoint X="25.770038604736328" Y="4.941671371459961" />
                                
<StylusPoint X="25.770038604736328" Y="4.941671371459961" />
                                
<StylusPoint X="27.19110870361328" Y="4.206720352172852" />
                                
<StylusPoint X="28.171157836914062" Y="3.7167530059814453" />
                                
<StylusPoint X="29.102203369140625" Y="3.2757816314697265" />
                                
<StylusPoint X="29.690235137939453" Y="2.981801986694336" />
                                
<StylusPoint X="29.690235137939453" Y="2.981801986694336" />
                                
<StylusPoint X="30.278263092041015" Y="2.736818313598633" />
                                
<StylusPoint X="30.278263092041015" Y="2.736818313598633" />
                                
<StylusPoint X="30.278263092041015" Y="2.736818313598633" />
                                
<StylusPoint X="30.033252716064453" Y="3.324777603149414" />
                                
<StylusPoint X="29.837242126464843" Y="3.765748977661133" />
                                
<StylusPoint X="29.298213958740234" Y="4.59869384765625" />
                                
<StylusPoint X="28.75918960571289" Y="5.67662239074707" />
                                
<StylusPoint X="27.975147247314453" Y="7.195520401000977" />
                                
<StylusPoint X="27.2401123046875" Y="8.861410140991211" />
                                
<StylusPoint X="26.35806655883789" Y="10.821279525756836" />
                                
<StylusPoint X="25.5250244140625" Y="12.830144882202148" />
                                
<StylusPoint X="24.789989471435547" Y="14.790014266967773" />
                                
<StylusPoint X="24.201961517333984" Y="16.65188980102539" />
                                
<StylusPoint X="23.858943939208984" Y="18.317779541015625" />
                                
<StylusPoint X="23.809940338134765" Y="19.689685821533203" />
                                
<StylusPoint X="24.103954315185547" Y="20.522632598876953" />
                                
<StylusPoint X="24.740985870361328" Y="20.91460418701172" />
                                
<StylusPoint X="25.770038604736328" Y="20.91460418701172" />
                                
<StylusPoint X="27.28911590576172" Y="20.375640869140625" />
                                
<StylusPoint X="29.200210571289062" Y="19.395706176757812" />
                                
<StylusPoint X="29.200210571289062" Y="19.395706176757812" />
                                
<StylusPoint X="31.356319427490234" Y="18.072795867919922" />
                                
<StylusPoint X="33.70843505859375" Y="16.455902099609375" />
                                
<StylusPoint X="36.20756149291992" Y="14.594026565551757" />
                                
<StylusPoint X="38.75568771362305" Y="12.683155059814453" />
                                
<StylusPoint X="41.15680694580078" Y="10.772281646728515" />
                                
<StylusPoint X="41.15680694580078" Y="10.772281646728515" />
                                
<StylusPoint X="43.410919189453125" Y="8.910406112670898" />
                                
<StylusPoint X="45.273014068603516" Y="7.391508102416992" />
                                
<StylusPoint X="46.74308776855469" Y="6.117591857910156" />
                                
<StylusPoint X="47.82114028930664" Y="5.186655044555664" />
                                
<StylusPoint X="48.55617904663086" Y="4.696687698364258" />
                                
<StylusPoint X="48.55617904663086" Y="4.696687698364258" />
                                
<StylusPoint X="48.55617904663086" Y="4.696687698364258" />
                                
<StylusPoint X="48.55617904663086" Y="5.725618362426758" />
                                
<StylusPoint X="47.91914749145508" Y="6.999532699584961" />
                                
<StylusPoint X="47.08610534667969" Y="8.46943473815918" />
                                
<StylusPoint X="46.05705261230469" Y="10.33131217956543" />
                                
<StylusPoint X="44.979000091552734" Y="12.340177536010742" />
                                
<StylusPoint X="44.979000091552734" Y="12.340177536010742" />
                                
<StylusPoint X="43.85194396972656" Y="14.398040771484375" />
                                
<StylusPoint X="42.82289123535156" Y="16.406906127929687" />
                                
<StylusPoint X="42.82289123535156" Y="16.406906127929687" />
                                
<StylusPoint X="41.94084548950195" Y="18.219783782958984" />
                                
<StylusPoint X="41.30381393432617" Y="19.88567352294922" />
                                
<StylusPoint X="41.30381393432617" Y="19.88567352294922" />
                                
<StylusPoint X="40.91179656982422" Y="21.159587860107422" />
                                
<StylusPoint X="40.86279296875" Y="22.139522552490234" />
                                
<StylusPoint X="41.15680694580078" Y="22.62948989868164" />
                                
<StylusPoint X="41.74483871459961" Y="22.72748565673828" />
                                
<StylusPoint X="42.67588424682617" Y="22.33551025390625" />
                                
<StylusPoint X="43.85194396972656" Y="21.60055923461914" />
                                
<StylusPoint X="45.37101745605469" Y="20.620624542236328" />
                                
<StylusPoint X="47.03710174560547" Y="19.297714233398437" />
                                
<StylusPoint X="48.85019302368164" Y="17.82781219482422" />
                                
<StylusPoint X="50.71228790283203" Y="16.161922454833984" />
                                
<StylusPoint X="52.574378967285156" Y="14.54503059387207" />
                                
<StylusPoint X="54.43647003173828" Y="12.928138732910156" />
                                
<StylusPoint X="56.2005615234375" Y="11.605226516723632" />
                                
<StylusPoint X="56.2005615234375" Y="11.605226516723632" />
                                
<StylusPoint X="57.81764221191406" Y="10.380308151245117" />
                                
<StylusPoint X="59.140708923339844" Y="9.449369430541992" />
                                
<StylusPoint X="60.21875762939453" Y="8.763416290283203" />
                                
<StylusPoint X="61.100807189941406" Y="8.371442794799804" />
                                
<StylusPoint X="61.73783874511719" Y="8.371442794799804" />
                                
<StylusPoint X="61.73783874511719" Y="8.371442794799804" />
                                
<StylusPoint X="62.22785949707031" Y="9.498367309570312" />
                                
<StylusPoint X="62.08085632324219" Y="10.62529182434082" />
                                
<StylusPoint X="61.68883514404297" Y="12.242183685302734" />
                                
<StylusPoint X="61.100807189941406" Y="14.251049041748046" />
                                
<StylusPoint X="60.36576843261719" Y="16.602893829345703" />
                                
<StylusPoint X="59.53273010253906" Y="19.15072250366211" />
                                
<StylusPoint X="58.65068054199219" Y="21.74755096435547" />
                                
<StylusPoint X="57.81764221191406" Y="24.246383666992187" />
                                
<StylusPoint X="57.082603454589844" Y="26.69622039794922" />
                                
<StylusPoint X="56.5435791015625" Y="28.75408172607422" />
                                
<StylusPoint X="56.29856872558594" Y="30.419971466064453" />
                                
<StylusPoint X="56.347564697265625" Y="31.497901916503906" />
                                
<StylusPoint X="56.78858947753906" Y="31.93886947631836" />
                                
<StylusPoint X="57.5726318359375" Y="31.791881561279297" />
                                
<StylusPoint X="58.797691345214844" Y="31.20391845703125" />
                                
<StylusPoint X="60.36576843261719" Y="30.17498779296875" />
                                
<StylusPoint X="62.42387390136719" Y="28.70508575439453" />
                                
<StylusPoint X="64.62898254394531" Y="27.039196014404297" />
                                
<StylusPoint X="66.9811019897461" Y="25.079326629638672" />
                                
<StylusPoint X="69.43122100830078" Y="23.119457244873047" />
                                
<StylusPoint X="71.83234405517578" Y="21.257583618164062" />
                                
<StylusPoint X="74.18445587158203" Y="19.54269790649414" />
                                
<StylusPoint X="76.38957214355469" Y="18.072795867919922" />
                                
<StylusPoint X="78.34967041015625" Y="16.847877502441406" />
                                
<StylusPoint X="78.34967041015625" Y="16.847877502441406" />
                                
<StylusPoint X="79.96675109863281" Y="15.916938781738281" />
                                
<StylusPoint X="81.33881378173828" Y="15.27998161315918" />
                                
<StylusPoint X="82.36786651611328" Y="14.986000061035156" />
                                
<StylusPoint X="83.15190887451172" Y="15.083993911743164" />
                                
<StylusPoint X="83.64192962646484" Y="15.57396125793457" />
                                
<StylusPoint X="83.7889404296875" Y="16.504899978637695" />
                                
<StylusPoint X="83.49492645263672" Y="17.77881622314453" />
                                
<StylusPoint X="83.00489807128906" Y="19.4447021484375" />
                                
<StylusPoint X="82.31886291503906" Y="21.208587646484375" />
                                
<StylusPoint X="81.53482818603515" Y="23.16845703125" />
                                
<StylusPoint X="80.75078582763672" Y="25.030330657958984" />
                                
<StylusPoint X="79.96675109863281" Y="26.843212127685547" />
                            
</StylusPointCollection>
                        
</Stroke.StylusPoints>
                    
</Stroke>
                
</StrokeCollection>
            
</InkPresenter.Strokes>
        
</InkPresenter>
        
<CheckBox Name="Erase"  Content="橡皮擦" ToolTipService.ToolTip="选中后可擦除指定画笔" />
        
<!--InkPresenter End-->
    
</StackPanel>
</Canvas>

     InkMenu.xaml.cs:


public partial class InkMenu : UserControl
{
    
public InkMenu()
    {
        InitializeComponent();
        
this.Loaded += new RoutedEventHandler(InkMenu_Loaded);
    }

    
void InkMenu_Loaded(object sender, RoutedEventArgs e)
    {
        inkAttributes = inkPreview.Strokes[0].DrawingAttributes;
        inkAttributes.Color = GetColor(inkFillSlider.Value);
        inkAttributes.OutlineColor = GetColor(inkStrokeSlider.Value);
        inkAttributes.Width = inkAttributes.Height = inkThicknessSlider.Value * 10d;
    }

    
#region 橡皮擦点击事件
    
/// <summary>
    
/// 橡皮擦点击事件
    
/// </summary>
    public event RoutedEventHandler Click
    {
        add
        {
            Erase.Click += value;
        }
        remove
        {
            Erase.Click -= value;
        }
    }
    
#endregion

    
#region 获取颜色值

    
public DrawingAttributes inkAttributes;

    
void inkStrokeSlider_ValueChanged(object sender, EventArgs e)
    {
        
byte alpha = inkAttributes.OutlineColor.A;
        inkAttributes.Color = GetColor(inkStrokeSlider.Value, alpha);
    }

    
void inkFillSlider_ValueChanged(object sender, EventArgs e)
    {
        
byte alpha = inkAttributes.Color.A;
        inkAttributes.Color = GetColor(inkFillSlider.Value, alpha);
    }

    
void inkThicknessSlider_ValueChanged(object sender, EventArgs e)
    {
        inkAttributes.Width = inkThicknessSlider.Value * 10d;
        inkAttributes.Height = inkThicknessSlider.Value * 10d;
    }

    
void inkTransparencySlider_ValueChanged(object sender, EventArgs e)
    {
        Color color = inkAttributes.Color;
        Color outlineColor = inkAttributes.OutlineColor;
        inkAttributes.Color = Color.FromArgb((byte)Math.Floor(256d * (1d - inkTransparencySlider.Value)), color.R, color.G, color.B);
        inkAttributes.OutlineColor = Color.FromArgb((byte)Math.Floor(256d * (1d - inkTransparencySlider.Value)), outlineColor.R, outlineColor.G, outlineColor.B);
    }

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

    
/// <summary>
    
/// 将滑动条值(Value)转换为ARGB 颜色值并返回
    
/// </summary>
    
/// <param name="alpha">alpha通道,该值介于0到255</param>
    
/// <returns>ARGB 颜色值</returns>
    private Color GetColor(double value, byte alpha)
    {
        Color color;
      
        
// 将滑动条的值转换为 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;
    }
    
#endregion
}


    另外涂鸭的底层实现代码位于AdvanceMode.xaml.cs中:


 #region Ink 事件代码
 
/// <summary>
 
/// Ink 事件代码
 
/// </summary>
 public enum InkEditingMode
 {
     None,
     Ink,
     Erase
 }
 
/// <summary>
 
/// InkEditingMode模式,默认为Ink
 
/// </summary>
 private InkEditingMode editingMode = InkEditingMode.Ink;

 
private Stroke inkStroke = null;

 
private StylusPointCollection erasePoints = null;

 
void onInkPresenterDown(object sender, MouseButtonEventArgs e)
 {
     
if (editingMode == InkEditingMode.None)
         
return;

     (sender as FrameworkElement).CaptureMouse();
     StylusPointCollection stylusPoints = e.StylusDevice.GetStylusPoints(InkCanvas);

     
if (editingMode == InkEditingMode.Erase)
     {
         erasePoints = new StylusPointCollection();
         erasePoints.Add(stylusPoints);
     }
     
else if (editingMode == InkEditingMode.Ink)
     {
         inkStroke = new Stroke();
         inkStroke.StylusPoints.Add(stylusPoints);
         inkStroke.DrawingAttributes = new DrawingAttributes();
         inkStroke.DrawingAttributes.Color = inkMenu.inkAttributes.Color;
         inkStroke.DrawingAttributes.OutlineColor = inkMenu.inkAttributes.OutlineColor;
         inkStroke.DrawingAttributes.Width = inkMenu.inkAttributes.Width;
         inkStroke.DrawingAttributes.Height = inkMenu.inkAttributes.Height;
         InkCanvas.Strokes.Add(inkStroke);
     }
 }

 
void SetEditingMode()
 {
     
if (EditInkMode.IsChecked == true)
     {
         
if (inkMenu.Erase.IsChecked == false)
             editingMode = InkEditingMode.Ink;
         
else
             editingMode = InkEditingMode.Erase;
     }
     
else
         editingMode = InkEditingMode.None;
 }

 
void onInkPresenterMove(object sender, MouseEventArgs e)
 {
     SetEditingMode();
     
if (editingMode == InkEditingMode.None) return;
     StylusPointCollection stylusPoints = e.StylusDevice.GetStylusPoints(InkCanvas);

     
if (editingMode == InkEditingMode.Erase)
     {
         
if (erasePoints != null)
         {
             
// hittest and erase
             erasePoints.Add(stylusPoints);
             StrokeCollection hitStrokes = InkCanvas.Strokes.HitTest(erasePoints);
             
for (int i = 0; i < hitStrokes.Count; i++)
             {
                 InkCanvas.Strokes.Remove(hitStrokes[i]);
             }
         }
     }
     
else if (editingMode == InkEditingMode.Ink)
     {
         
if (inkStroke != null)
         {
             inkStroke.StylusPoints.Add(stylusPoints);
         }
     }
 }

 
void onInkPresenterEnter(object sender, MouseButtonEventArgs e)
 {
     
if (EditInkMode.IsChecked == true)
     {
          
if (inkMenu.Erase.IsChecked == false)
             editingMode = InkEditingMode.Ink;
          
else
             editingMode = InkEditingMode.Erase;
     }
     
else
         editingMode = InkEditingMode.None;

     erasePoints = null;
     inkStroke = null;
 }

 
void onInkPresenterUp(object sender, MouseButtonEventArgs e)
 {
     
if (editingMode == InkEditingMode.None)
         
return;

     
if (inkStroke != null)
     {
         inkStroke.StylusPoints.Add(e.StylusDevice.GetStylusPoints(InkCanvas));
     }
     (sender as FrameworkElement).ReleaseMouseCapture();
     erasePoints = null;
     inkStroke = null;
 }

 
private void EditInkMode_Click(object sender, RoutedEventArgs e)
 {
     
if (EditInkMode.IsChecked == true)
     {
         inkMenu.Visibility = System.Windows.Visibility.Visible;
         
if (inkMenu.Erase.IsChecked == false)
             editingMode = InkEditingMode.Ink;
         
else
             editingMode = InkEditingMode.Erase;
     }
     
else
     {
         inkMenu.Visibility = System.Windows.Visibility.Collapsed;
         editingMode = InkEditingMode.None;
     }
 }

 
private void Erase_Click(object sender, RoutedEventArgs e)
 {
     inkMenu.Visibility = System.Windows.Visibility.Visible;
     
if (inkMenu.Erase.IsChecked == false)
         editingMode = InkEditingMode.Ink;
     
else
         editingMode = InkEditingMode.Erase;
 }

 
#endregion

    

      当然就目前产品代码的结构而言还不够优化,特别是重复的代码段还有一些,不过不影响大家的最终使用,鉴于目前本人的经历和时间有限,所以就把它开源出来,大家如果感兴趣可以在其基础上加入更新的功能来完善它,呵呵。


      好了,今天的内容就先到这里了, 源码下载链接,请点击这里

      相关链接: 

           目前为止功能最全的基于silverlight4(beta)的摄像头应用 

           基于silverlight4(beta)的摄像头应用(Beta2)发布 

 

     原文链接:  http://www.cnblogs.com/daizhj/archive/2010/08/31/1813437.html

     作者: daizhj, 代震军

     Tags: silverlight,webcam

     网址: http://daizhj.cnblogs.com/

posted @ 2010-08-31 11:37  代震军  阅读(4902)  评论(40编辑  收藏  举报