赞
踩
需要一个自用的浏览器,最好是用ChromiumWeb内核快速开发,下面使用Visual Studio 开发工具新建一个桌面程序WinForm项目,实现一个基本上网浏览功能使用即可
选择项目,鼠标右键选择打开Nuget程序包管理器,插件上找CefSharp
安装好,如下图所示,由于此插件只支持x64或x86的处理器,若编译运行不了就设置编译为x64或x86即可
把窗口布局弄成大致如下图所示
窗口有包括返回、刷新、关闭、(搜索)访问、打印、开发者工具按钮等,还有输入框
用的两大组件: TabControl,ToolStrip,里面在包含一些子组件Label,TextBox,Button…
public partial class Form2 : Form
{
ChromiumWebBrowser mChromium;
public Form2()
{
InitializeComponent();
InitializeChromium();//调用初始化浏览器方法
}
private void InitializeChromium()
{
var tempPath = Path.Combine(System.Environment.GetEnvironmentVariable("TMP"), "mybrowser");//用户临时目录
if (Directory.Exists(tempPath)!=true)
{
Directory.CreateDirectory(tempPath);
}
var settings = new CefSettings();
settings.UserDataPath = Path.Combine(tempPath, "userData");
settings.CachePath = Path.Combine(tempPath, "cache");//缓存路径
settings.LogFile = Path.Combine(tempPath, "logFile");//日志文件
//settings.ResourcesDirPath = Path.Combine(tempPath, "resDir");
//settings.No = true;
//settings.Locale = "zh-CN";
//settings.LocalesDirPath = Path.Combine(tempPath, "localesDir");
settings.AcceptLanguageList = "zh-CN,zh;q=0.8";//引擎语言
settings.PersistSessionCookies = true;
settings.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.102 Safari/537.36";
CefSharp.Cef.Initialize(settings, true);
if (CefSharpSettings.ShutdownOnExit)
{
Application.ApplicationExit += OnApplicationExit;//设置退出时调用的方法事件
}
tabControl1.TabPages[0].Text = "主页";
tabControl1.TabPages[1].Text = "loading...";
var url = toolStripTextBox1.Text;//使用默认地址
OpenNewBrowser(tabControl1.SelectedIndex + 1, url);//打开浏览器方法
}
private void OnApplicationExit(object sender, EventArgs e)
{
Cef.Shutdown();//释放资源
}
}
4.打开浏览器方法,实现细节很多,代码如下
public partial class Form2 : Form
{
private void OpenNewBrowser(int tabIndex, string url)
{
var browser = new ChromiumWebBrowser(url);
//var browser = new ChromiumWebBrowser();
//标题改变事件
browser.TitleChanged += new EventHandler<TitleChangedEventArgs>(delegate (object sender, TitleChangedEventArgs args) {
this.Invoke(new Action(delegate ()
{
if (tabIndex < tabControl1.TabPages.Count)
{
tabControl1.TabPages[tabIndex].Text = args.Title;
}
}));
});
//加载错误处理事件
browser.LoadError += new EventHandler<LoadErrorEventArgs>(delegate (object sender, LoadErrorEventArgs args) {
var errorTemplate = string.Format(HtmlTemplate.ErrorPage3, args.ErrorText, args.ErrorCode.ToString(), args.FailedUrl);
browser.LoadHtml(errorTemplate);
});
//状态改变事件 例如 用户鼠标指向的链接
browser.StatusMessage += new EventHandler<StatusMessageEventArgs>((object sender, StatusMessageEventArgs args) => {
this.Invoke(new Action(() => {
if (string.IsNullOrEmpty(args.Value))
{
label1.Text = "";
return;
}
label1.Text = string.Format("预点击链接:{0}", args.Value);
}));
});
//浏览器地址跳转 改变事件
browser.AddressChanged += new EventHandler<AddressChangedEventArgs>((object sender, AddressChangedEventArgs args) => {
this.Invoke(new Action(() => {
if (toolStripTextBox1.Focused != false) return;
toolStripTextBox1.Text = args.Address;
}));
});
//对打开新页面时做处理
browser.LifeSpanHandler = new CefLifeSpanHandler((IWindowInfo windowInfo, String targetUrl) => {
this.Invoke(new Action(() => {
tabControl1.TabPages.Add(targetUrl);
OpenNewBrowser(tabControl1.TabPages.Count - 1, targetUrl);
}));
});
//下载事件
browser.DownloadHandler = new CefDownloadHandler("_007",(String targetUrl, String id) => {
var res = MessageBox.Show(String.Format("下载完成,是否打开文件位置?\n{0}", targetUrl), "系统提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Information);
if (res == DialogResult.OK)
{
openExplorer(targetUrl);//打开文件位置
}
return true;
});
//鼠标右键菜单
browser.MenuHandler = new CefMenuHandler();
browser.Dock = System.Windows.Forms.DockStyle.Fill;
//添加浏览器组件
tabControl1.TabPages[tabIndex].Controls.Add(browser);
if (tabControl1.SelectedIndex != tabIndex)
{
tabControl1.SelectedIndex = tabIndex;
}
}
}
CefLifeSpanHandler
,CefDownloadHandler
,CefMenuHandler
,贴上代码如下public class CefLifeSpanHandler : CefSharp.ILifeSpanHandler
{
Action<IWindowInfo, String> onNewWindow;
public CefLifeSpanHandler(Action<IWindowInfo, String> OnNewWindow)
{
this.onNewWindow = OnNewWindow;
}
public bool DoClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
if (browser.IsDisposed || browser.IsPopup)
{
return false;
}
return true;
}
public void OnAfterCreated(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
//throw new NotImplementedException();
}
public void OnBeforeClose(IWebBrowser chromiumWebBrowser, IBrowser browser)
{
//throw new NotImplementedException();
}
public bool OnBeforePopup(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, string targetUrl, string targetFrameName, WindowOpenDisposition targetDisposition, bool userGesture, IPopupFeatures popupFeatures, IWindowInfo windowInfo, IBrowserSettings browserSettings, ref bool noJavascriptAccess, out IWebBrowser newBrowser)
{
if (onNewWindow != null)
{
onNewWindow(windowInfo, targetUrl);//调用传入的方法
}
newBrowser = null;
return true;
}
}
public class CefDownloadHandler : CefSharp.IDownloadHandler
{
Func<string, string, bool> calDownload;
String id;
public CefDownloadHandler(String id, Func<string, string, bool> calDownload)
{
this.calDownload = calDownload;
this.id = id;
}
public bool CanDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, string url, string requestMethod)
{
return true;
}
public void OnBeforeDownload(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IBeforeDownloadCallback callback)
{
callback.Continue(downloadItem.Url, true);
}
public void OnDownloadUpdated(IWebBrowser chromiumWebBrowser, IBrowser browser, DownloadItem downloadItem, IDownloadItemCallback callback)
{
if (downloadItem.IsComplete != true) return;
//下载成功时调用
calDownload(downloadItem.FullPath, id);
}
}
//封装命令集的类 如枚举
class MenuCommand
{
public static CefMenuCommand CopySelectText = (CefMenuCommand) 1000011;
public static CefMenuCommand DownloadSave = (CefMenuCommand) 1000012;
public static CefMenuCommand CopyLink = (CefMenuCommand) 1000013;
}
public class CefMenuHandler : CefSharp.IContextMenuHandler
{
public void OnBeforeContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model)
{
if (model.Count>0)
{
model.AddSeparator();
}
if (!String.IsNullOrEmpty(parameters.SourceUrl))
{
if (parameters.MediaType != ContextMenuMediaType.None)
{
model.AddItem(MenuCommand.DownloadSave, "save file");//保存文件
}
}
else if (!String.IsNullOrEmpty(parameters.LinkUrl))
{
var reg = new Regex("\\.\\w+$");
if (reg.IsMatch(parameters.LinkUrl))
{
model.AddItem(MenuCommand.DownloadSave, "save file");//保存文件
} else
{
model.AddItem(MenuCommand.CopyLink, "copy link");//复制链接
}
return;
}
}
public bool OnContextMenuCommand(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, CefMenuCommand commandId, CefEventFlags eventFlags)
{
if (commandId == MenuCommand.CopyLink)
{
Clipboard.SetText(parameters.SelectionText);
}
else if (commandId == MenuCommand.DownloadSave)
{
var cbrowser = chromiumWebBrowser as ChromiumWebBrowser;
if (!string.IsNullOrEmpty(parameters.SourceUrl))
{
cbrowser.StartDownload(parameters.SourceUrl);
return true;
}
else if (!string.IsNullOrEmpty(parameters.LinkUrl))
{
cbrowser.StartDownload(parameters.LinkUrl);
return true;
}
}
return false;
}
public void OnContextMenuDismissed(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame)
{
var cbrowser = chromiumWebBrowser as ChromiumWebBrowser;
cbrowser.Invoke(new Action(() =>
{
cbrowser.ContextMenu = null;
}));
}
public bool RunContextMenu(IWebBrowser chromiumWebBrowser, IBrowser browser, IFrame frame, IContextMenuParams parameters, IMenuModel model, IRunContextMenuCallback callback)
{
return false; //可弹出
}
}
public partial class Form2 : Form
{
ChromiumWebBrowser mChromium;
public Form2()
{
InitializeComponent();
InitializeChromium();
}
private void InitializeChromium()
{
//...
}
private void OpenNewBrowser(int tabIndex, string url)
{
//...
}
/// <summary>
/// 打开文件位置
/// </summary>
/// <param name="filePath">文件路径</param>
private void openExplorer(string filePath)
{
filePath = filePath.Replace("/", "\\");//此处的路径都要求是右斜杠的’\’才能定位打开
System.Diagnostics.ProcessStartInfo psi = new System.Diagnostics.ProcessStartInfo("Explorer.exe");
psi.Arguments = "/e,/select," + filePath;
System.Diagnostics.Process.Start(psi);
}
private void Form2_Load(object sender, EventArgs e)
{
}
private void OnApplicationExit(object sender, EventArgs e)
{
//...
}
private void Form2_FormClosing(object sender, FormClosingEventArgs e)
{
try
{
for(int i=1; i< tabControl1.Controls.Count; i++)
{
var control = tabControl1.Controls[i];
if (control.Controls.Count <= 0) continue;
CloseBrowser(control.Controls[0] as ChromiumWebBrowser);
control.Controls.Clear();
}
//KillBrowserSubprocess();//杀死进程
//if (isShutdown) CefSharp.Cef.Shutdown();//释放资源
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString(), "清理CefSharp.BrowserSubprocess异常");
}
}
private void CloseBrowser(ChromiumWebBrowser cefBrowser)
{
cefBrowser.JavascriptObjectRepository.UnRegisterAll();//解绑对象 高版本才有
cefBrowser.CloseDevTools();//关闭调试
cefBrowser.GetBrowser().CloseBrowser(true);//关闭浏览器
cefBrowser.Dispose();
}
//刷新按钮点击
private void toolStripButton2_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
browser.Refresh();
}
//获取当前选项卡下的浏览窗口
private ChromiumWebBrowser GetCurrorBrowser()
{
if (tabControl1.SelectedIndex < 1) return null;
return tabControl1.SelectedTab.Controls[0] as ChromiumWebBrowser;
}
//返回按钮点击
private void toolStripButton1_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
browser.Back();
}
//关闭当前选项卡
private void toolStripButton3_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
//TODO: 有Bug,当它删掉两个就会挂掉 错误未知 需要优化
CloseBrowser(browser);
if (tabControl1.SelectedIndex > 0)
{
tabControl1.SelectedIndex--;
tabControl1.TabPages.RemoveAt(tabControl1.SelectedIndex + 1);
}
}
//地址输入框 的 访问按钮点击
private void toolStripButton4_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
var text = toolStripTextBox1.Text.Trim();
if (string.IsNullOrEmpty(text)) return;
if (!text.StartsWith("http"))
{
if (!text.StartsWith("//"))
{
text = "//" + text;
}
if (!text.StartsWith(":"))
{
text = ":" + text;
}
}
if (toolStripTextBox1.Text.Contains(text))
{
toolStripTextBox1.Text = text;
}
browser.LoadUrlAsync(text);
}
//主页 百度一下 按钮点击
private void button1_Click(object sender, EventArgs e)
{
var text = textBox1.Text.Trim();
if (string.IsNullOrEmpty(text)) return;
var url = "https://www.baidu.com/s?ie=utf-8&wd=" + HttpUtility.UrlEncode(text);
tabControl1.TabPages.Add(url);
OpenNewBrowser(tabControl1.TabPages.Count-1, url);
}
//打印按钮点击
private void toolStripButton5_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
browser.Print();
}
//打开开发者工具 控制台 调试
private void toolStripButton6_Click(object sender, EventArgs e)
{
var browser = GetCurrorBrowser();
if (browser == null) return;
browser.ShowDevTools();
}
}
HtmlTemplate
类,是一个基本网页模板代码,还是贴出来参考,代码如下public class HtmlTemplate
{
internal static readonly string ErrorPage3 = "<!doctype html>" +
"<html>" +
"<head>" +
"<meta charset=\"utf-8\" />" +
"<title>Error Page</title>" +
"</head>" +
"<body style=\"padding: 20px; background-color: #0000ff; color: #ffffff;\">" +
"<h1>:(</h1>" +
"<h3>{0}</h3>" +
"<hr/>" +
"<p>错误信息:{1}</p>" +
"<p>错误地址:<a style=\"opacity: 0.5; color: chartreuse; text-decoration: none;\" href=\"javascript:return false;\">{2}</a></p>" +
"</body>" +
"</html>";
}
8.就记录到这了,收工!
该浏览器只实现后,经过测试如下:
- 支持HTML5标准
- 可下载文件
- 可播放视频MP4
在线播放其它视频格式暂时不支持- 可自定义右键菜单
已禁止播放flash插件- 其它…脚本与浏览器通信…未测
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。