Chromium Embedded Framework (CEF) を C# から使えるようにしたプロジェクトのうちの1つに、
CefSharp というものがあります。
WinForms, WPF, OffScreen 用にそれぞれパッケージが用意されており、 NuGet からも導入できます。
そのうち、 OffScreen には、描画部分をスクショする機能があるのですが、
WinForms 及び WPF プロジェクトには提供されていないので、自前実装しました。
基本的には、 OffScreen の実装を WPF 向けに移植しただけです。
/// <summary> /// Extend CefSharp ChromiumWebBrowser for Snapshot /// </summary> internal class ChromiumWebBrowser2 : ChromiumWebBrowser { private readonly object _lockObj = new object(); private ImageFormat _format; private bool _isTakingSnapshot; private string _path; public ChromiumWebBrowser2() { _isTakingSnapshot = false; Rendering += OnRendering; } public void TakingSnapshot(string path, ImageFormat format) { if (!WebBrowser.IsBrowserInitialized || WebBrowser.IsLoading || _isTakingSnapshot) return; lock (_lockObj) { _path = path; _format = format; _isTakingSnapshot = true; } } // InvokeRenderAsync private void OnRendering(object sender, RenderingEventArgs e) { if (_isTakingSnapshot) Snapshot(e.BitmapInfo); } private void Snapshot(BitmapInfo bitmapInfo) { var stride = bitmapInfo.Width * bitmapInfo.BytesPerPixel; lock (_lockObj) { var snapshot = (InteropBitmap) Imaging.CreateBitmapSourceFromMemorySection(bitmapInfo.FileMappingHandle, bitmapInfo.Width, bitmapInfo.Height, PixelFormats.Bgra32, stride, 0); using (var stream = new FileStream(_path, FileMode.Create)) { var encoder = _format.GetBitmapEncoder(); encoder.Frames.Add(BitmapFrame.Create(snapshot)); encoder.Save(stream); } } _isTakingSnapshot = false; } }
ちなみに ImageFormat
はこれ。
public enum ImageFormat { Bmp, Png, Jpeg } public static class ImageFormatExt { public static string GetImageExtension(this ImageFormat obj) => obj.ToString().ToLower(); public static BitmapEncoder GetBitmapEncoder(this ImageFormat obj) { switch (obj) { case ImageFormat.Bmp: return new BmpBitmapEncoder(); case ImageFormat.Jpeg: return new JpegBitmapEncoder(); case ImageFormat.Png: return new PngBitmapEncoder(); default: throw new ArgumentOutOfRangeException(nameof(obj), obj, null); } } }
使い方は、 ChromiumWebBrowser
の代わりに ChromiumWebBrowser2
を使って、
任意のタイミングで TakingSnapshot
を呼べば OK 。