转自:http://www.cnblogs.com/tmywu/archive/2010/09/14/1825650.html
在WPF中我们可以将Canvas当成一种画布,将Canvas中的控件当成元素,讲其转成位图文件:
如下效果
图1.1
你可以设置Canvas的宽度、高度和颜色类型,生成任何你想要的图片。实时呈现你设置的样式等效果。
包括创建一些特效如阴影等。
WPF提供RenderTargetBitmap类将任何容器控件渲染成一个位图。
新建一个WPF项目,在页面中创建一个CANVAS,如下:
2 <TextBlock Canvas.Left="200" Canvas.Top="50" x:Name="VSSize" text="Canvs 转换为图片"></TextBlock>
3 </Canvas>
在CS代码中做处理:
RenderTargetBitmap bmp = new RenderTargetBitmap(this.Screen.Width, this.Screen.Height, 96, 96, PixelFormats.Pbgra32); bmp.Render(this.Screen); string file = @"c:\xxx.jpg"; string Extension = System.IO.Path.GetExtension(file).ToLower(); BitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (Stream stm = File.Create(file)) { encoder.Save(stm); }
这样就将CANVAS转换成图1.1的效果;
如果你对生成的图片有更高的清晰度的要求,你可以设置encoder的QualityLevel属性来改变JPEG的质量值,或者生成质量更高的PNG图片,如
我们改变下CANVAS的一些属性,将一个名为SCREEN的CANVAS 放在另一个CANVAS中并设置上偏移50,设置如下:
<Canvas>
<Canvas Canvas.Top="50" x:Name="Screen" Width="700" Height="200" Background="#F0CC0000">
<TextBlock Canvas.Left="200" Canvas.Top="50" x:Name="VSSize" text="Canvs 转换为图片"></TextBlock>
</Canvas>
</Canvas>
后台CS代码不变;
效果如下:
图片上出现一条黑块,将此图片放入PHOTOSHOP中可看见居上偏移50为一透明块,证明任何属性的偏移对CANVAS的构图都会造成影响。
那么直接在后台CS文件中建一个CANVAS直接生成位图是否可以?如下:
Canvas cvs = new Canvas(); cvs.Width = 700; cvs.Height = 200; Label lb = new Label(); lb.content = "Canvas 转换为 图片"; Canvas.SetTop(lb,50); Canvas.Setleft(lb,200); cvs.child.add(lb); RenderTargetBitmap bmp = new RenderTargetBitmap(cvs.Width, cvs.Height, 96, 96, PixelFormats.Pbgra32); bmp.Render(cvs); string file = @"c:\xxx.jpg"; string Extension = System.IO.Path.GetExtension(file).ToLower(); BitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (Stream stm = File.Create(file)) { encoder.Save(stm); }
运行代码,保存成的图像为一张700*200的空位图,说明直接在后台构造的容器无法直接转为位图。
解决办法:
RenderTargetBitmap.Render的对象为一个Visual对象,界面元素都继承自Visual对象。
我们可以建一个虚拟画布对象,如DrawingVisual drawingVisual = new DrawingVisual();
以此为基础使用DrawingContext对象将Canvas及其Child中的对象在DrawingVisual 虚画布上重新进行构图,然后Render DrawingVisual 就可以生成一张位图了。
示例:
Canvas cvs = new Canvas(); cvs.Width = 700; cvs.Height = 200; Label lb = new Label(); lb.content = "Canvas 转换为 图片"; Canvas.SetTop(lb,50); Canvas.Setleft(lb,200); cvs.child.add(lb); DrawingVisual drawingVisual = new DrawingVisual(); DrawingContext drawingContext = drawingVisual.RenderOpen(); //构造一个矩形 Rect rect = new Rect(new System.Windows.Point(0, 0), new System.Windows.Point(cvs.ActualWidth, cvs.ActualHeight)); //画一个矩形 drawingContext.DrawRectangle(cvs.Background, new System.Windows.Media.Pen(), rect); //画文字 drawingContext.DrawText(new FormattedText(), new System.Windows.Point(Canvas.GetLeft(lb), Canvas.GetTop(lb))); drawingContext.Close(); RenderTargetBitmap bmp = new RenderTargetBitmap(cvs.Width, cvs.Height, 96, 96, PixelFormats.Pbgra32); //Render DrawingVisual bmp.Render(drawingVisual); string file = @"c:\xxx.jpg"; string Extension = System.IO.Path.GetExtension(file).ToLower(); BitmapEncoder encoder = new JpegBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(bmp)); using (Stream stm = File.Create(file)) { encoder.Save(stm); }