Silverlight 4实现在线大头贴程序,支持打印

Silverlight 4提供了许多的新特性,如摄像头、打印等。这里我就用Silverlight 4做了一个在线照大头贴的小东西。

先放效果图:

效果1.jpg效果2.jpg效果3.jpg效果4.jpg

项目结构如下图所示:

项目结构.jpg

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>

效果如下:

主界面设计图.jpg

后台代码:

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

posted @ 2009-12-18 09:25  齐.net  阅读(1145)  评论(6编辑  收藏  举报