WPF控件导出为PNG:用RenderTargetBitmap
+ JpegBitmapEncoder
/PngBitmapEncoder
WPF不支持直接调用
DrawToBitmap,必须走渲染管线。核心是把控件渲染到
RenderTargetBitmap,再编码保存。注意:控件需已加载(
IsLoaded == true),且不能处于隐藏状态(
Visibility == Visibility.Visible)。
常见错误是控件未布局完成就截图,结果为空白或尺寸为0。建议在
Loaded事件或
Dispatcher.InvokeAsync中执行:
var bitmap = new RenderTargetBitmap((int)control.ActualWidth, (int)control.ActualHeight, 96, 96, PixelFormats.Pbgra32);
bitmap.Render(control);
<p>var encoder = new PngBitmapEncoder();
encoder.Frames.Add(BitmapFrame.Create(bitmap));</p><p>using var fs = File.OpenWrite("output.png");
encoder.Save(fs);关键点:
ActualWidth/ActualHeight必须在布局完成后读取,否则为0 分辨率参数(96)影响清晰度,高DPI下可设为
VisualTreeHelper.GetDpi(control).PixelsPerInchX若控件含
Effect(如模糊、阴影),需确保
RenderOptions.SetBitmapScalingMode(control, BitmapScalingMode.HighQuality)导出透明背景用
PngBitmapEncoder;导出JPEG会丢弃Alpha通道
WinForm控件截图:用Control.DrawToBitmap
但注意裁剪和DPI缩放
DrawToBitmap是WinForm原生方案,但默认不处理DPI缩放——高DPI下截图会模糊或错位。必须先手动调整目标
Bitmap尺寸,并启用
Graphics的高质量渲染。
典型写法:
var bmp = new Bitmap(control.Width * control.DeviceDpi / 96, control.Height * control.DeviceDpi / 96);
using (var g = Graphics.FromImage(bmp))
{
g.InterpolationMode = InterpolationMode.HighQualityBicubic;
g.SmoothingMode = SmoothingMode.HighQuality;
g.PixelOffsetMode = PixelOffsetMode.HighQuality;
control.DrawToBitmap(bmp, new Rectangle(0, 0, bmp.Width, bmp.Height));
}
bmp.Save("output.jpg", ImageFormat.Jpeg);易踩坑:
直接传control.Size给
Bitmap构造函数 → 高DPI下图像被压缩拉伸 忽略
control.DeviceDpi,硬编码96 → 多屏DPI不一致时出错
DrawToBitmap无法捕获重叠在控件之上的浮层(如
ToolTip、菜单) 某些自绘控件(如第三方图表)可能绕过GDI绘制,需调用其专属导出接口
跨窗口/全屏截图:用Graphics.CopyFromScreen
或Desktop duplication API
如果要截整个窗口(含非客户区)或桌面,
DrawToBitmap和
RenderTargetBitmap都失效。此时得用屏幕坐标抓取。
简单场景用
CopyFromScreen(WinForm兼容):
var bounds = control.PointToScreen(new Point(0, 0));
var bmp = new Bitmap(control.Width, control.Height);
using (var g = Graphics.FromImage(bmp))
g.CopyFromScreen(bounds, Point.Empty, control.Size);但该方法有局限:
仅适用于可见区域,最小化窗口返回黑图 多显示器+不同DPI时,PointToScreen返回值需用
Monitor.FromPoint校准 性能差,不适合高频截图(如录屏)
生产环境建议用Windows Desktop Duplication API(C++/COM),C#可通过
SharpDX或
Windows.Graphics.Capture(Win10 1803+)调用,支持捕获最小化窗口、硬件加速、Alpha通道。
保存路径与权限:避免UnauthorizedAccessException
和中文路径乱码
截图保存失败最常见原因是路径不可写或含非法字符。WPF/WinForm默认运行在用户上下文,但若程序以管理员身份运行,而目标目录(如
C:\Program Files)受UAC保护,就会抛
UnauthorizedAccessException。
安全做法:
优先保存到Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData)或
MyDocuments路径含中文时,确保文件系统支持UTF-8(NTFS没问题,FAT32需注意) 使用
Path.Combine拼接路径,避免手动加反斜杠导致
DirectoryNotFoundException保存前检查父目录是否存在:
Directory.CreateDirectory(Path.GetDirectoryName(filePath))
另外,
FileStream未显式指定
FileAccess.Write或未用
using释放,在部分杀毒软件下可能被拦截写入。
