主にプログラミング関連のメモ帳 ♪(✿╹ヮ╹)ノ
書いてあるコードは自己責任でご自由にどうぞ。記事本文の無断転載は禁止です。
2016/06/29
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 。