曾经想要保存自己想要的存在的价值,用浏览器的功能,总是有一部分不尽如人意。
系统自带的打印,部分页面显示不全,感觉无法生成我想要的PDF或者PNG。
1、创建.Net Framework项目,选择版本4.7.2

1、创建窗体应用
2、使用Nuget安装CefSharp.WinForms(一个内置浏览器,来实现相应功能)

2、安装CefSharp.WinForms
3、窗体布局(注:Anchor参数可使WEB窗体大小自动,方便截图打印)

页面布局.png
4、代码编写(利用CefSharp.WinForms自带的CaptureScreenshotAsync功能实现)
using CefSharp.WinForms;
using CefSharp;
using System;
using System.Windows.Forms;
using System.IO;
using System.Collections.Generic;
namespace 火焰山网页打印
{
public partial class Form1 : Form
{
private const string HistoryFilePath = "history.txt"; // 历史记录文件路径
private const int MaxHistoryLines = 200; // 最大历史记录行数
public Form1()
{
InitializeComponent();
InitializeChromium();
}
private void InitializeChromium()
{
var settings = new CefSettings
{
CachePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "CefSharp\\Cache"), // 设置缓存路径
Locale = "zh-CN" // 设置语言为中文
};
Cef.Initialize(settings);
textBox1.Text = "https://www.bing.com"; // 修复URL
this.FormClosing += new FormClosingEventHandler(Form1_FormClosing);
chromiumWebBrowser1.AddressChanged += ChromiumWebBrowser1_AddressChanged;
comboBox1.TextChanged += ComboBox1_TextChanged;
// 设置 LifeSpanHandler
chromiumWebBrowser1.LifeSpanHandler = new CustomLifeSpanHandler();
}
private void ComboBox1_TextChanged(object sender, EventArgs e)
{
try
{
chromiumWebBrowser1.Load(comboBox1.Text);
}
catch (Exception) { }
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
chromiumWebBrowser1.Load(textBox1.Text);
}
catch (Exception) { }
}
public class CustomLifeSpanHandler : ILifeSpanHandler
{
public bool OnBeforePopup(IWebBrowser browserControl, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
// 禁止新窗口的创建,强制在当前窗口中打开链接
browser.MainFrame.LoadUrl(targetUrl);
newBrowser = null;
return true;
}
public void OnAfterCreated(IWebBrowser browserControl, IBrowser browser)
{
}
public bool DoClose(IWebBrowser browserControl, IBrowser browser)
{
return false;
}
public void OnBeforeClose(IWebBrowser browserControl, IBrowser browser)
{
}
}
private void LoadHistory()
{
try
{
if (File.Exists(HistoryFilePath))
{
string[] lines = File.ReadAllLines(HistoryFilePath);
// 确保在UI线程上操作
if (InvokeRequired)
{
Invoke(new Action(() =>
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
HashSet<string> uniqueUrls = new HashSet<string>(); // 创建一个 HashSet 用于存储唯一的 URL
foreach (string line in lines)
{
string[] parts = line.Split(new string[] { "<<->>" }, StringSplitOptions.None);
if (parts.Length > 1)
{
string url = parts[1].Trim(); // 获取 URL 并去除首尾空格
if (!uniqueUrls.Contains(url)) // 检查 URL 是否已经存在
{
comboBox1.Items.Add(url); // 将 URL 添加到 ComboBox 中
uniqueUrls.Add(url); // 将 URL 添加到 HashSet 中,用于去重
}
}
}
}));
}
else
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
foreach (string line in lines)
{
string[] parts = line.Split(new string[] { "<<->>" }, StringSplitOptions.None);
if (parts.Length > 1)
{
comboBox1.Items.Add(parts[1].Trim()); // 将 URL 添加到 ComboBox 中
}
}
}
}
else {
// 确保在UI线程上操作
if (InvokeRequired)
{
Invoke(new Action(() =>
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
}));
}
else
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
}
}
}
catch (Exception) { }
}
private void DeleteHistory()
{
try
{
if (File.Exists(HistoryFilePath))
{
File.Delete(HistoryFilePath);
// 确保在UI线程上操作
if (InvokeRequired)
{
Invoke(new Action(() =>
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
}));
}
else
{
comboBox1.Items.Clear(); // 清空 ComboBox 中的现有条目
}
}
}
catch (Exception) { }
}
private void SaveHistory(string url)
{
try
{
string timestamp = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
string historyEntry = $"{timestamp} <<->> {url}";
// 读取现有历史记录
string[] lines = File.Exists(HistoryFilePath) ? File.ReadAllLines(HistoryFilePath) : new string[0];
// 添加新的历史记录
Array.Resize(ref lines, lines.Length + 1);
lines[lines.Length - 1] = historyEntry;
// 确保不超过最大行数
if (lines.Length > MaxHistoryLines)
{
Array.Resize(ref lines, MaxHistoryLines);
}
// 保存到文件
File.WriteAllLines(HistoryFilePath, lines);
}
catch (Exception) { }
}
private void ChromiumWebBrowser1_AddressChanged(object sender, AddressChangedEventArgs e)
{
try
{
SaveHistory(e.Address);
LoadHistory();
}
catch (Exception) { }
}
private void button1_Click(object sender, EventArgs e)
{
try
{
string url = textBox1.Text;
if (Uri.IsWellFormedUriString(url, UriKind.Absolute))
{
try
{
chromiumWebBrowser1.Load(url);
}
catch (Exception ex)
{
MessageBox.Show($"加载页面时发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("请输入有效的URL地址!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
catch (Exception) { }
}
private void button3_Click(object sender, EventArgs e)
{
try
{
if (chromiumWebBrowser1.CanGoBack)
{
chromiumWebBrowser1.Back();
}
}
catch (Exception) { }
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
// 关闭浏览器时释放资源
Cef.Shutdown();
}
catch (Exception) { }
}
private void button2_Click(object sender, EventArgs e)
{
try
{
string homePage = "https://nginx.mblue.ltd/navigation/my/link/myself/";
chromiumWebBrowser1.Load(homePage);
textBox1.Text = homePage;
}
catch (Exception) { }
}
private void button4_Click(object sender, EventArgs e)
{
try
{
if (chromiumWebBrowser1.CanGoForward)
{
chromiumWebBrowser1.Forward();
}
}
catch (Exception) { }
}
private void button5_Click(object sender, EventArgs e)
{
try
{
chromiumWebBrowser1.Reload();
}
catch (Exception) { }
}
private void button6_Click(object sender, EventArgs e)
{
try
{
chromiumWebBrowser1.Print();
}
catch (Exception) { }
}
private async void button8_Click(object sender, EventArgs e)
{
if (chromiumWebBrowser1.IsBrowserInitialized)
{
try
{
// 捕获当前页面为字节数组
// byte[] screenshotData = await chromiumWebBrowser1.CaptureScreenshotAsync();
// 捕获整个页面的截图
byte[] screenshotData = await chromiumWebBrowser1.CaptureScreenshotAsync(captureBeyondViewport: true);
string screenshotDirectory = Path.Combine(Environment.CurrentDirectory, "screenshot");
if (!Directory.Exists(screenshotDirectory))
{
Directory.CreateDirectory(screenshotDirectory); // 如果目录不存在,则创建目录
}
string screenshotFileName = Guid.NewGuid().ToString() + ".png"; // 使用 UUID 生成文件名
string screenshotPath = Path.Combine(screenshotDirectory, screenshotFileName);
File.WriteAllBytes(screenshotPath, screenshotData);
MessageBox.Show($"截图已保存到: {screenshotPath}", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"截图时发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("浏览器尚未初始化,请稍后再试!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private async void button9_Click(object sender, EventArgs e)
{
if (chromiumWebBrowser1.IsBrowserInitialized)
{
try
{
// 捕获整个页面的截图
byte[] screenshotData = await chromiumWebBrowser1.CaptureScreenshotAsync(captureBeyondViewport: true);
// 保存字节数组到文件
string screenshotPath = Path.Combine(Environment.CurrentDirectory, "screenshot.png");
File.WriteAllBytes(screenshotPath, screenshotData);
MessageBox.Show($"截图已保存到: {screenshotPath}", "成功", MessageBoxButtons.OK, MessageBoxIcon.Information);
}
catch (Exception ex)
{
MessageBox.Show($"截图时发生错误: {ex.Message}", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("浏览器尚未初始化,请稍后再试!", "错误", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private void button9_Click_1(object sender, EventArgs e)
{
try
{
DeleteHistory();
}
catch (Exception) { }
}
}
}
4、程序展示

窗体网页加载完成
4、结果展示

窗体网页加载完成,截屏打印结果示例