我在尝试将网页另存为图片时遇到问题,所有内容在我的应用程序中都能正常运行,直到保存部分。
string desktopPath = Environment.GetFolderPath(System.Environment.SpecialFolder.DesktopDirectory);
string imageFileName = desktopPath + browserView.Browser.URL.ToString();
browserView1.GetImage().Save(@imageFileName, ImageFormat.Png);
这会抛出错误
App.exe
中发生了未处理的“System.NullReferenceException”类型异常附加信息:对象引用未设置为的实例 对象
使用对话框保存它很奇怪,工作正常:
if (saveFileDialog.ShowDialog() == DialogResult.OK)
{
string imageFileName = saveFileDialog.FileName.ToString().Replace("%.png%", "");
browserView1.GetImage().Save(imageFileName, ImageFormat.Png);
}
有什么想法吗?我只是希望保存图像而不需要对话或用户交互,并将其保存到桌面文件夹。
答案 0 :(得分:1)
要获取指定网页的屏幕截图,您需要按照以下步骤操作:
注意:以下示例中使用的OnRepaint事件仅支持轻量级渲染模式。 GetImage()方法适用于两种模式,但在调用此方法之前,应嵌入并显示该组件。
示例强>
以下示例演示如何捕获完整网页的图像。在这种情况下,您甚至不需要嵌入浏览器视图。
using DotNetBrowser;
using DotNetBrowser.Events;
using DotNetBrowser.WPF;
using System;
using System.Drawing.Imaging;
using System.Threading;
using System.Windows;
namespace HTMLToImageSample
{
public partial class WindowMain : Window
{
private WPFBrowserView browserView;
public WindowMain()
{
this.Loaded += delegate
{
Width = 400;
Height = 300;
browserView = new WPFBrowserView(BrowserFactory.Create(BrowserType.LIGHTWEIGHT));
Browser browser = browserView.Browser;
// #1 Set browser initial size
browserView.Browser.SetSize(1280, 1024);
// #2 Load web page and wait until web page is loaded completely.
ManualResetEvent resetEvent = new ManualResetEvent(false);
FinishLoadingFrameHandler listener = new FinishLoadingFrameHandler((object sender, FinishLoadingEventArgs e) =>
{
if (e.IsMainFrame)
{
resetEvent.Set();
}
});
browser.FinishLoadingFrameEvent += listener;
try
{
browser.LoadURL("teamdev.com/dotnetbrowser");
resetEvent.WaitOne(new TimeSpan(0, 0, 45));
}
finally
{
browser.FinishLoadingFrameEvent -= listener;
}
// #3 Set the required document size.
JSValue documentHeight = browserView.Browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollHeight, " +
"document.documentElement.scrollHeight, document.body.offsetHeight, " +
"document.documentElement.offsetHeight, document.body.clientHeight, " +
"document.documentElement.clientHeight);");
JSValue documentWidth = browserView.Browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollWidth, " +
"document.documentElement.scrollWidth, document.body.offsetWidth, " +
"document.documentElement.offsetWidth, document.body.clientWidth, " +
"document.documentElement.clientWidth);");
int scrollBarSize = 25;
int viewWidth = (int)documentWidth.GetNumber() + scrollBarSize;
int viewHeight = (int)documentHeight.GetNumber() + scrollBarSize;
// #4 Register OnRepaint to get notifications
// about paint events. We expect that web page will be completely rendered twice:
// 1. When its size is updated.
// 2. When HTML content is loaded and displayed.
ManualResetEvent waitEvent = new ManualResetEvent(false);
DrawingView drawingView = (DrawingView)browserView.GetInnerView();
drawingView.OnRepaint += delegate(object sender, OnRepaintEventArgs e)
{
// Make sure that all view content has been repainted.
if (e.UpdatedRect.Size.Equals(e.ClientSize))
{
waitEvent.Set();
}
};
browserView.Browser.SetSize(viewWidth, viewHeight);
// #5 Wait until Chromium renders web page content.
waitEvent.WaitOne();
// #6 Save Image of the loaded web page into a PNG file.
Dispatcher.BeginInvoke((Action)(() =>
{
browserView.GetImage().Save(@"teamdev.png", ImageFormat.Png);
}));
};
}
[STAThread]
public static void Main()
{
Application app = new Application();
WindowMain wnd = new WindowMain();
app.Run(wnd);
var browser = wnd.browserView.Browser;
wnd.browserView.Dispose();
browser.Dispose();
}
}
}
如果您需要获取包含可滚动隐藏部分的整个网页的屏幕截图,而您不知道网页尺寸,则需要使用以下方法进行计算:
JSValue documentHeight = browser.ExecuteJavaScriptAndReturnValue(
"Math.max(document.body.scrollHeight, " +
"document.documentElement.scrollHeight, document.body.offsetHeight, " +
"document.documentElement.offsetHeight, document.body.clientHeight, " +
"document.documentElement.clientHeight);");
JSValue documentWidth = browser.executeJavaScriptAndReturnValue(
"Math.max(document.body.scrollWidth, " +
"document.documentElement.scrollWidth, document.body.offsetWidth, " +
"document.documentElement.offsetWidth, document.body.clientWidth, " +
"document.documentElement.clientWidth);");
int scrollBarSize = 25;
int viewWidth = (int) documentWidth.GetNumber() + scrollBarSize;
int viewHeight = (int) documentHeight.GetNumber() + scrollBarSize;
在此代码中,我们使用JavaScript和DOM API来获取已加载文档的尺寸。
完整的示例解决方案可以在本文的附件中找到。此解决方案中的项目具有NuGet依赖项,将在构建期间自动解析。
如果您尝试捕获较长的网页,您可能已经注意到图像被剪切为很长的页面。此行为是由Chromium内部的限制引起的。 Chromium在画布上呈现网页的内容,最大高度设置为16384.如果网页的高度超过最大纹理大小,则不会绘制Chromium画布外部的网页部分,并将填充黑色。 要解决此限制并捕获高度超过最大纹理大小的网页的完整图像,您应在创建任何Browser或BrowserView实例之前指定以下开关:
int viewWidth = 1024;
int viewHeight = 20000;
string[] switches = {
"--disable-gpu",
"--max-texture-size=" + viewHeight
};
BrowserPreferences.SetChromiumSwitches(switches);
如果指定了这些开关,GPU进程将被禁用,Chromium最大纹理大小将从16384更改为viewHeight。
注意:在DotNetBrowser 1.9中引入了--max-texture-size开关。