在去年年底,为了学习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:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
< 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个小矩形的枚举标识:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/// <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
主要的控件类实体,实现各种相关鼠标操作事件和图形绘制事件代码(详见注释):
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
{
#region 属性设置
/// <summary>
/// 8个允许调整控件大小的小正方形
/// </summary>
Rectangle[] SmallRect = new Rectangle[ 8 ];
/// <summary>
/// 8个小正方形的大小
/// </summary>
Size Square = new Size( 6 , 6 );
/// <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),采取动态加载控件方式来加载菜单项并绑定相应事件(如打印):
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/// 初始化右键菜单
/// </summary>
void InitPopMenu()
{
Border border = new Border()
{
BorderBrush = new SolidColorBrush(Color.FromArgb( 255 , 167 , 171 , 176 )),
CornerRadius = new CornerRadius( 2 ),
BorderThickness = new Thickness( 1 ),
Background = new SolidColorBrush(Colors.White),
Effect = new DropShadowEffect() { BlurRadius = 3 , Color = Color.FromArgb( 255 , 230 , 227 , 236 ) }
};
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;
}
下面就是菜单项的样式绑定代码:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/// 加载菜单项
/// </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( 255 , 233 , 238 , 238 )) });
grid.Children.Add( new Rectangle() { Fill = new SolidColorBrush(Color.FromArgb( 255 , 226 , 228 , 231 )), HorizontalAlignment = HorizontalAlignment.Right, Width = 1 });
Button roButton = new Button()
{
Height = 22 ,
Margin = new Thickness( 0 , 0 , 0 , 0 ),
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( 1 , 0 , 0 , 0 ) };
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( 16 , 0 , 0 , 0 ), Text = menuName });
roButton.Content = sp;
grid.Children.Add(roButton);
return grid;
}
接下来就是用户选择下载或打印的实现代码(里面的JpegHelper类是一个将WriteableBitmap转为jpeg图片的辅助类):
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/// 保存到本地
/// </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);
}
}
}
}
下面是打印代码:
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/// <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):
![](https://i-blog.csdnimg.cn/blog_migrate/81178cc93a2a3bb5048d90d76e7ec935.gif)
/// 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:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
<!-- 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:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
{
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 ), 0 , 0 );
}
else if (value < 0.286d )
{
color = Color.FromArgb(alpha, ( byte )Math.Floor(256d * ( 0.286d - value) / 0.143d ), ( byte )Math.Floor(256d * (value - 0.143d ) / 0.143d ), 0 );
}
else if (value < 0.429 )
{
color = Color.FromArgb(alpha, 0 , ( byte )Math.Floor(256d * ( 0.429d - value) / 0.143d ), ( byte )Math.Floor(256d * (value - 0.286d ) / 0.143d ));
}
else if (value < 0.571 )
{
color = Color.FromArgb(alpha, 0 , ( byte )Math.Floor(256d * (value - 0.429d ) / 0.143d ), 255 );
}
else if (value < 0.714 )
{
color = Color.FromArgb(alpha, ( byte )Math.Floor(256d * (value - 0.571d ) / 0.143d ), ( byte )Math.Floor(256d * ( 0.714d - value) / 0.143d ), 255 );
}
else if (value < 0.857 )
{
color = Color.FromArgb(alpha, 255 , ( byte )Math.Floor(256d * (value - 0.714d ) / 0.143d ), ( byte )Math.Floor(256d * ( 0.857d - value) / 0.143d ));
}
else
{
color = Color.FromArgb(alpha, 255 , 255 , ( byte )Math.Floor(256d * (value - 0.857d ) / 0.143d ));
}
return color;
}
#endregion
}
另外涂鸭的底层实现代码位于AdvanceMode.xaml.cs中:
![](https://i-blog.csdnimg.cn/blog_migrate/cdec0645add3fc3c328197dda5c76203.gif)
/// <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