Silverlight 4实现在线大头贴程序,支持打印
Silverlight 4提供了许多的新特性,如摄像头、打印等。这里我就用Silverlight 4做了一个在线照大头贴的小东西。
先放效果图:
项目结构如下图所示:
template目录里存放的是一些简单的遮罩模板,这些模板都实现了IFillBrushable接口。
主界面(Page.xaml)的主要代码如下:
<Grid x:Name="LayoutRoot"> <Grid x:Name="grdRender" Width="180" Height="180" Margin="10,10,200,100" ShowGridLines="False"> </Grid> <Button Content="保存" Height="23" HorizontalAlignment="Left" Margin="12,251,0,0" x:Name="btnSave" VerticalAlignment="Top" Width="75" Click="btnSave_Click" /> <Button Content="捕获" Height="23" HorizontalAlignment="Left" Margin="12,214,0,0" x:Name="btnCapture" VerticalAlignment="Top" Width="75" Click="btnCapture_Click" /> <Button Content="导入" Height="23" HorizontalAlignment="Left" Margin="104,214,0,0" x:Name="btnImport" VerticalAlignment="Top" Width="75" Click="btnImport_Click" /> <Button Content="打印" Height="23" HorizontalAlignment="Left" Margin="104,251,0,0" x:Name="btnPrint" VerticalAlignment="Top" Width="75" Click="btnPrint_Click" /> <ListBox Height="200" HorizontalAlignment="Left" Margin="228,10,0,0" Name="lstTemplate" VerticalAlignment="Top" Width="110" SelectionChanged="lstTemplate_SelectionChanged" > </ListBox> <Grid.Background> <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0"> <GradientStop Color="#FF524040" Offset="0" /> <GradientStop Color="#FFD8BCBC" Offset="1" /> <GradientStop Color="#FF3E3A3A" Offset="0.26" /> </LinearGradientBrush> </Grid.Background> </Grid>
效果如下:
后台代码:
public partial class Page : UserControl { UserControl render = null; public Page() { InitializeComponent(); //Load事件 this.Loaded += (sender, e) => { //加载默认的遮罩模板 render = new starTemp() { Margin = new Thickness(0), FillBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)) }; grdRender.Children.Add(render); //绑定模板数据到ListBox BindTemplateControl(); }; } private void btnSave_Click(object sender, RoutedEventArgs e) { //创建WriteableBitmap WriteableBitmap wb = new WriteableBitmap(grdRender, null); SaveFileDialog sfd = new SaveFileDialog(); sfd.ShowDialog(); if (!string.IsNullOrEmpty(sfd.SafeFileName.Trim())) { using (Stream stream = sfd.OpenFile()) { // 将WriteableBitmap数据写入到Stream SaveBitmap(wb, stream); //关闭保存流 stream.Close(); } } } /// <summary> /// 将WriteableBitmap数据写入到Stream /// </summary> /// <param name="bitmap"></param> /// <param name="fs"></param> private void SaveBitmap(WriteableBitmap bitmap, Stream fs) { int pixelWidth = bitmap.PixelWidth; int pixelHeight = bitmap.PixelHeight; int num3 = 3; byte[][,] bufferArray = new byte[num3][,]; for (int i = 0; i < num3; i++) { bufferArray[i] = new byte[pixelWidth, pixelHeight]; } for (int j = 0; j < pixelHeight; j++) { for (int k = 0; k < pixelWidth; k++) { int num7 = bitmap.Pixels[(pixelWidth * j) + k]; bufferArray[0][k, j] = (byte)(num7 >> 0x10); bufferArray[1][k, j] = (byte)(num7 >> 8); bufferArray[2][k, j] = (byte)num7; } } ColorModel model2 = new ColorModel() { colorspace = ColorSpace.RGB }; ColorModel model = model2; FluxJpeg.Core.Image image = new FluxJpeg.Core.Image(model, bufferArray); MemoryStream stream = new MemoryStream(); new JpegEncoder(image, 100, stream).Encode(); stream.Seek(0L, SeekOrigin.Begin); byte[] buffer = new byte[stream.Length]; long num8 = stream.Read(buffer, 0, (int)stream.Length); fs.Write(buffer, 0, buffer.Length); } private void OnStart() { //实例化CaptureSource CaptureSource source = new CaptureSource(); //是否请允许访问设备 bool blnAllowedDeviceAccess = CaptureDeviceConfiguration.AllowedDeviceAccess; //请求设备,返回是否成功 bool blnRequestDeviceAccess = CaptureDeviceConfiguration.RequestDeviceAccess(); //禁止访问设备则返回 if (blnAllowedDeviceAccess || !blnRequestDeviceAccess) return; //设置捕获的视频设备 source.VideoCaptureDevice = CaptureDeviceConfiguration.GetDefaultVideoCaptureDevice(); //新建一个VideoBrush VideoBrush videoBrush = new VideoBrush(); //设置VideoBrush的数据源 videoBrush.SetSource(source); //设置grdRender的背景为videoBrush grdRender.Background = videoBrush; //捕获 source.Start(); } private void btnCapture_Click(object sender, RoutedEventArgs e) { OnStart(); } /// <summary> /// 导入遮罩图片 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnImport_Click_Click(object sender, RoutedEventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.ShowDialog(); if (ofd.File != null) { //创建ImageBrush ImageBrush ib = new ImageBrush(); //打开的图片文件的流 Stream stream = ofd.File.OpenRead(); var bmp = new BitmapImage(); //填充到BitmapImage中 bmp.SetSource(stream); ib.ImageSource = bmp; //设置为遮罩控件的FillBursh (render as IFillBrushable).FillBrush = ib; } } private void btnPrint_Click(object sender, RoutedEventArgs e) { //创建打印文档对象 PrintDocument pd = new PrintDocument(); //设置文档标题 pd.SetValue(PrintDocument.DocumentNameProperty, "大头贴"); //设置打印区,为render对象 pd.PrintPage += (ppsender, ppe) => { ppe.PageVisual = render; }; pd.Print(); } private void BindTemplateControl() { //获取当前程序集 var assembly = Assembly.GetExecutingAssembly(); //根据Namespace取类型 Type[] types = assembly.GetTypes().Where(p => p.Namespace == "SilverlightApplication1.template").ToArray(); //设置lstTemplate的数据源为上面类型的名称集合 lstTemplate.ItemsSource = from mod in types select mod.Name; lstTemplate.UpdateLayout(); } /// <summary> /// ListBox选择项改变 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void lstTemplate_SelectionChanged(object sender, SelectionChangedEventArgs e) { //先清楚grdRender的子控件,即遮罩控件 grdRender.Children.Clear(); //分所当前选择的第一项改变 switch (e.AddedItems[0].ToString()) { case "hart": render = new hartTemp() { Margin = new Thickness(0), FillBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)) }; grdRender.Children.Add(render); break; case "Star": render = new starTemp() { Margin = new Thickness(0), FillBrush = new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)) }; grdRender.Children.Add(render); break; } } }
遮罩模板接口:
/// <summary> /// 遮罩控件层接口 /// </summary> public interface IFillBrushable { /// <summary> /// 遮挡区的填充画笔 /// </summary> Brush FillBrush { get; set; } }
然后就是遮罩模板控件,如心形遮罩控件的Xaml如下:
<Grid x:Name="LayoutRoot" Background="#00FF0000" > <Path x:Name="pathMask" Stretch="UniformToFill" Stroke="Black" StrokeThickness="0" HorizontalAlignment="Left" VerticalAlignment="Top" UseLayoutRounding="False" Data="M130,10.504693 C110.25,10.755516 90.5,21.039251 90.5,41.105072 C90.5,0.97377241 10.5,0.9732672 10.500001,41.105072 C10.5,81.236885 90.5,161.50002 90.5,161.50002 C90.5,161.50002 169.5,80.233429 169.5,40.10178 C169.5,20.035959 149.75,10.253871 130,10.504693 z M0.5,0.5 L179.5,0.5 L179.5,171.5 L0.5,171.5 z"> </Path> </Grid>
后台代码如下(一定要实现IFillBrushable接口):
public partial class hartTemp : UserControl, IFillBrushable { #region 是实现FillBrush属性 public static DependencyProperty FillBrushProperty; public Brush FillBrush { get { return base.GetValue(FillBrushProperty) as Brush; } set { base.SetValue(FillBrushProperty, value); } } static void OnFillBrushChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e) { (sender as hartTemp).OnFillBrushChanged(e); } void OnFillBrushChanged(DependencyPropertyChangedEventArgs e) { pathMask.Fill = e.NewValue as Brush; } #endregion public hartTemp() { FillBrushProperty = DependencyProperty.Register("FillBrush", typeof(Brush), typeof(hartTemp), new PropertyMetadata(new SolidColorBrush(Color.FromArgb(255, 255, 0, 0)), new PropertyChangedCallback(hartTemp.OnFillBrushChanged))); InitializeComponent(); } }
其它的内容可以下载附件中的源码。
注意:开发调试环境为Vs2010 B2版 ,Silverlight 4。由于没有摄像头所以我这里用了个虚拟摄像头放的是视频。
源码下载:附件:CaptureTest.rar