原文 将控件保存为图片
将控件保存为图片
周银辉
这里分别提供win form 和 wpf 两种方式
对于.net 2.0 我们可以简单地利用 BitBlt 函数来实现,非常简单,代码如下:
public
static
class
ControlToImageConverter
{
private const Int32 SRCCOPY = 0xCC0020 ;
[DllImport( " gdi32.dll " )]
internal static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);
public static Bitmap GetImageOfControl(Control control)
{
var w = control.Size.Width;
var h = control.Size.Height;
Graphics gOfCtrl = control.CreateGraphics();
var bmp = new Bitmap(w, h, gOfCtrl);
Graphics gOfBmp = Graphics.FromImage(bmp);
IntPtr dc1 = gOfCtrl.GetHdc();
IntPtr dc2 = gOfBmp.GetHdc();
BitBlt(dc2, 0 , 0 , w, h, dc1, 0 , 0 , SRCCOPY);
gOfCtrl.ReleaseHdc(dc1);
gOfBmp.ReleaseHdc(dc2);
gOfCtrl.Dispose();
gOfBmp.Dispose();
return bmp;
}
}
{
private const Int32 SRCCOPY = 0xCC0020 ;
[DllImport( " gdi32.dll " )]
internal static extern bool BitBlt(
IntPtr hdcDest, // handle to destination DC
int nXDest, // x-coord of destination upper-left corner
int nYDest, // y-coord of destination upper-left corner
int nWidth, // width of destination rectangle
int nHeight, // height of destination rectangle
IntPtr hdcSrc, // handle to source DC
int nXSrc, // x-coordinate of source upper-left corner
int nYSrc, // y-coordinate of source upper-left corner
Int32 dwRop // raster operation code
);
public static Bitmap GetImageOfControl(Control control)
{
var w = control.Size.Width;
var h = control.Size.Height;
Graphics gOfCtrl = control.CreateGraphics();
var bmp = new Bitmap(w, h, gOfCtrl);
Graphics gOfBmp = Graphics.FromImage(bmp);
IntPtr dc1 = gOfCtrl.GetHdc();
IntPtr dc2 = gOfBmp.GetHdc();
BitBlt(dc2, 0 , 0 , w, h, dc1, 0 , 0 , SRCCOPY);
gOfCtrl.ReleaseHdc(dc1);
gOfBmp.ReleaseHdc(dc2);
gOfCtrl.Dispose();
gOfBmp.Dispose();
return bmp;
}
}
其中 SRCCOPY = 0xCC0020, 表示将源直接拷贝到目标。
对于WPF,无法获得控件的hdc, 所以不能使用bitblt函数了,但幸运的是,其提供了一个RenderTargetBitmap的类型,可以将控件绘制到改类型的类型是示例上,比如:
var renderBitmap
=
new RenderTargetBitmap(w, h, 96d,96d, PixelFormats.Pbgra32);
renderBitmap.Render(controlToConvert);
new RenderTargetBitmap(w, h, 96d,96d, PixelFormats.Pbgra32);
renderBitmap.Render(controlToConvert);
其可以直接作为Image控件的源以便显示,如果要将其保存下来(保存到流中),则需要用到BitmapEncoder, 将上面的位图添加到encoder的帧中,然后调用save方法便可。
包装好的代码如下:
点击展开
注意到上面的GetImageOfControl方法返回的实际是BitmapFrame, 其是BitmapSource的一种,如果你更习惯使用BitmapImage的话,免费赠送如下方法:
public
static
BitmapImage ToBitmapImage(
this
BitmapSource bitmapSource)
{
var encoder = new JpegBitmapEncoder();
var memoryStream = new MemoryStream();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(memoryStream);
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(memoryStream.ToArray());
bmp.EndInit();
memoryStream.Flush();
memoryStream.Close();
return bmp;
}
{
var encoder = new JpegBitmapEncoder();
var memoryStream = new MemoryStream();
encoder.Frames.Add(BitmapFrame.Create(bitmapSource));
encoder.Save(memoryStream);
var bmp = new BitmapImage();
bmp.BeginInit();
bmp.StreamSource = new MemoryStream(memoryStream.ToArray());
bmp.EndInit();
memoryStream.Flush();
memoryStream.Close();
return bmp;
}