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