基于Chromium构建Chrome WebBrowser for .net 控件(还有点心得体会)

http://blog.csdn.net/lllllllllluoyi/article/details/8540054

首先向360说句sorry,在2011年360极速浏览器出现的时候我去他们论坛里骂过。为什么要到歉呢,因为2012年我把我们公司使用IE WebBrowser改为Chrome控件了,中间遇到的辛酸使我明白360公司能做成产品确实不容易。言归正转,公司的壳程序是C#编写的WinForm程序,刚开始我只找到delphi的Chromium项目,然后在delphi2010中安装好控件后就生成DLL让WinForm程序调用,这种策略是我做这个控件的最大失败。因为我对delphi比较熟,很快控件就能在WinForm程序里跑起来了,很开心,立马根据壳中已经使用的事件和方法在自定义控件中实现,自测一下没有问题后就交给测试人员来试用,半天的功夫,测试员小张就来对我说:罗兄,网页中不能使用键盘上Tab键切换,回车事件响应不了......不会吧,是不是焦点没有定位到自定义控件中,我第一时间就是这样想,然后就是反复的折腾,还是不行。最后Google了一下,好不容易找到一个让自己信服的答案,就是win32的消息循环机制与.net消息机制不一样,嵌入到WinForm中的VCL控件不能得到消息。我靠,这还得了,leader还不把我劈了,leader已经吩咐美工全按chrome浏览器的样式来写了。兵来将挡,水来土淹,我火速Google一个能在.net上跑的版本“CefSharp”  ,下载来看,傻眼了,是C++版的,咋办?熬夜啃吧!

我分为了两个项目,一是libfuncs,为了使DLL名称一致,我重命名了CefSharp项目,它负责提供操作浏览器的方法和触发事件;二是cwber,它是自定义的WinForm控件,用于在Form上的布局,必须引用libfuncs.dll。

源码地址:https://sourceforge.net/projects/chromewebbrowse

cwber比较简单,以下是它的代码:

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Text;
using System.Windows.Forms;
using libfuncs;namespace cwber
{public partial class ChromeWebBrowser : UserControl{private ChromeApp chrome = null;ToolTip myToolTip = new ToolTip();public ChromeWebBrowser(){InitializeComponent();ChromeWebBrowser.CheckForIllegalCrossThreadCalls = false;}private void ChromeWebBrowser_Load(object sender, EventArgs e){if (chrome == null){chrome = new ChromeApp();}Start();}#region 外部调用方法libfuncs.DocumentCompletedEvent elementEvent1;libfuncs.FrameLoadStartEvent elementEvent2;libfuncs.FrameLoadEndEvent elementEvent3;libfuncs.FileDownloadingEvent fileDownloading;libfuncs.FileDownloadCompletedEvent fileDownloaded;libfuncs.ComponentInitialized componentInitialized;libfuncs.ToolTipEventListener toolTipEvent;public void Start(){if (chrome != null){chrome.Dock = DockStyle.Fill;if (componentInitialized == null){componentInitialized = new libfuncs.ComponentInitialized(componentInitializedEvent);chrome.RegisterEvent(componentInitialized);}Controls.Add(chrome);if (elementEvent1 == null){elementEvent1 = new libfuncs.DocumentCompletedEvent(documentComplete);chrome.RegisterEvent(elementEvent1);}if (elementEvent2 == null){elementEvent2 = new libfuncs.FrameLoadStartEvent(frameStartStart);chrome.RegisterEvent(elementEvent2);}if (elementEvent3 == null){elementEvent3 = new libfuncs.FrameLoadEndEvent(frameLoadEnd);chrome.RegisterEvent(elementEvent3);}if (fileDownloading == null){fileDownloading = new libfuncs.FileDownloadingEvent(this.downloading);chrome.RegisterEvent(fileDownloading);}if (fileDownloaded == null){fileDownloaded = new libfuncs.FileDownloadCompletedEvent(this.downloaded);chrome.RegisterEvent(fileDownloaded);}if (toolTipEvent == null){toolTipEvent = new libfuncs.ToolTipEventListener(this.ShowToolTipText);chrome.RegisterEvent(toolTipEvent);}chrome.Visible = true;chrome.BringToFront();}}/** 描述:释放浏览器*/public void Free(){elementEvent1 = null;elementEvent2 = null;elementEvent3 = null;fileDownloading = null;fileDownloaded = null;componentInitialized = null;toolTipEvent = null;chrome.Dispose();chrome = null;}/** 参数:Url 打开网页地址* 描述:打开网址。*/public void OpenUrl(string Url){if (chrome != null)chrome.Load(Url);}/** 参数:id 网页中的控件元素ID* 描述:根据元素ID获取元素的值,适用于Input,A标签元素*/public string GetElementValueById(string id){return chrome == null ? "" : chrome.GetElementValueById(id);}/** 参数:id 网页中的控件元素ID, value 元素新值* 描述:为页面中元素赋予新值。*/public void SetElementValueById(string id, string value){if (chrome != null){chrome.SetElementValueById(id, value);}}public delegate void TCallBackElementEventListener();private List<libfuncs.ElementEventListener> elementEventList = new List<libfuncs.ElementEventListener>();/** 描述:附加元素的侦听事件。当该元素触发附加事件时,则执行TCallBackElementEventListener委托方法*/public void AppendElementEventListener(string id, string eventName, TCallBackElementEventListener callFunc){libfuncs.ElementEventListener elementEvent = new libfuncs.ElementEventListener(callFunc);elementEventList.Add(elementEvent);chrome.AddElementEventListener(id, eventName, elementEvent);}/** 描述:向页面中注入并执行脚本。*/public void ExecuteScript(string script){if (chrome != null)chrome.ExecuteScript(script);}public object EvaluateScript(string script){if (chrome != null)return chrome.EvaluateScript(script);elsereturn null;}/** 描述:计算文件单位。用于文件下载。*/private string CompareFileSize(Int64 size){//计算K,M单位string strTotalSize = string.Empty;if (size < 1024){strTotalSize = size.ToString() + " B";}else if (size >= 1024 && size < 1024 * 1024){strTotalSize = (size / 1024).ToString() + " KB";}else{strTotalSize = (size / 1024 / 1024).ToString() + " MB";}return strTotalSize;}#endregion#region 属性public string Url{get{return chrome == null?"":chrome.Core.Address;}}#endregion#region 事件/*控件初始化事件*/public event EventHandler ComponentInitializedEventHandler;private void componentInitializedEvent(){EventArgs e = new EventArgs();if (ComponentInitializedEventHandler != null)ComponentInitializedEventHandler(this, e);}/*页面加载完成事件*/public event EventHandler DocumentCompletedEventHandler;private void documentComplete(){EventArgs e = new EventArgs();if (DocumentCompletedEventHandler != null)DocumentCompletedEventHandler(this, e);}/*Frame加载完成事件,这里的Frame可以是页面本身,也是iFrame元素*/public event EventHandler PageLoadFinishEventHandler;private void frameLoadEnd(){EventArgs e = new EventArgs();if (PageLoadFinishEventHandler != null)PageLoadFinishEventHandler(this, e);}/*Frame加载开始事件,这里的Frame可以是页面本身,也是iFrame元素*/public event EventHandler PageLoadStartEventHandler;private void frameStartStart(){EventArgs e = new EventArgs();if (PageLoadStartEventHandler != null)PageLoadStartEventHandler(this, e);}/*下载中事件,不开放该事件*/Form downloadForm = null;private void downloading(Int64 totalSize, Int64 loadedSize){string strTotalSize = CompareFileSize(totalSize);string strLoadedSize = CompareFileSize(loadedSize);if (downloadForm == null){downloadForm = new Form();downloadForm.Text = "下载中";downloadForm.Width = 280;downloadForm.Height = 150;downloadForm.MaximizeBox = false;downloadForm.MinimizeBox = false;downloadForm.ControlBox = false;downloadForm.StartPosition = FormStartPosition.CenterScreen;Label label = new Label();label.Left = 20;label.Top = 50;label.Width = 250;label.Text = "已下载:" + strLoadedSize + "/" + strTotalSize;downloadForm.Controls.Add(label);}downloadForm.Show();downloadForm.BringToFront();foreach (Control c in downloadForm.Controls){if (c is Label){Label label = (Label)c;label.Text = "已下载:" + strLoadedSize + "/" + strTotalSize;label.Update();}}downloadForm.Update();}/*下载完成事件,不开放该事件*/private void downloaded(){if (downloadForm != null)downloadForm.Close();downloadForm = null;}/*消息提示事件,不开放*/private void ShowToolTipText(string text){if (chrome == null) return;if (string.IsNullOrEmpty(text)){myToolTip.RemoveAll();return;}//保证每行40个字int len = text.Length;int offset = 40;int count = len / offset;for (int i = 1; i <= count; i++){text = text.Insert(offset * i, "\n");}myToolTip.ShowAlways = false;myToolTip.UseAnimation = true;myToolTip.UseFading = true;//t.SetToolTip(button1, text);Point p = Control.MousePosition;Point p1 = this.PointToClient(p);myToolTip.Show(text, chrome, p1.X+20, p1.Y+10);}#endregion}
}


重点是libfuncs中的libfuncs.h、ChromeApp.h、ChromeApp.cpp、ClientAdapter.h、ClientAdapter.cpp五个文件,实现方法都在里面,其他的文件基本都是接口文件。我自己只根据项目实际需求来做的功能,接口没有全部实现。这个部分大家看源代码吧,我用到的地方都注释了。文采不行,写不动,大家原谅。睡了。

最后说句,我们公司网页美工解脱了!

 

转载于:https://www.cnblogs.com/MaxWoods/p/4124856.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/423922.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

我们“老实”么?

我们“老实”么&#xff1f; 不知道现在的人&#xff0c;对老实这个词语是怎样的看法。“聪明”的人应该觉得那是个贬义词吧&#xff0c;因为他们总是在利用那些他们认为的“老实”人&#xff0c;有好事的时候他们想到的是那些他们畏惧或者讨好自己的人&#xff0c;有麻烦的时候…

从决策树到xgboost(一)

文章目录1 决策树1.1决策树定义1.2信息增益1.3 信息增益的算法1.4 信息增益比2 决策树ID32.1 ID3树的构建2.2 决策树的剪枝2.2.1 损失函数定义与计算2.2.2 剪枝过程2.3 CART树2.3.1 CART回归树2.3.2 CART分类树2.3.3 CART树剪枝1 决策树 1.1决策树定义 决策树的基本组成&…

网络媒体的赢利模式

首先我们先确定几个概念&#xff0c;网络媒体本质上是媒体的一种&#xff0c;它具有媒体的一切共性&#xff0c;同时它的经营也具有媒体经营的一切共性&#xff0c;而媒体除网络媒体以外&#xff0c;我们把其余的统称为传统媒体&#xff0c;其中又把电视、电台和报刊称之为传统…

从决策树到xgboost(二)

文章目录3 集成学习4 Adaboost4.1 Adaboost算法4.1.1 初始化训练数据的起始权值分布4.1.2 对m个弱分类器m1,2,3...M4.1.3 构建弱分类器的线性组合4.1.4 得到最终的分类器5 Boosting5.1 加法模型5.2 前向分布算法6 提升决策树BDT6.1 BDT算法6.2 回归问题提升树7 梯度提升决策树G…

[伤了昨天的心 裂成碎片和沙一起飞]五香里脊

今晨3点挂的电话&#xff0c;6点睁开的眼。困到头痛&#xff0c;但还是烧了道肉菜。…**…**…**…**…**…**…**…*分隔 五香里脊*…**…**…**…**…**…**…**…五香里脊 材料&#xff1a;1&#xff0e;里脊肉、油、麻油。2&#xff0e;蒜末、辣椒末、水、生抽、老醋、糖、…

python 字符串format使用

python字符串的格式化输出 格式化字符串是程序设计语言中用于指定输出参数的格式化与相对位置的字符串参数。其中的转换说明用于把随后的对应一个或多个函数参数转换为相应的格式输出&#xff1a;格式化字符串中转换说明以外的其他字符原样输出。 1>>>"I like %s…

MOTOMAN-SV3X运动学建模验证图

以下是正解&#xff0c;逆解 结果 转载于:https://www.cnblogs.com/wqj1212/archive/2008/01/01/1022177.html

极客时间算法练习题总结

文章出处&#xff1a;极客时间《数据结构和算法之美》-作者&#xff1a;王争。该系列文章是本人的学习笔记。 在极客时间《数据结构和算法之美》最后&#xff0c;王争老师加餐了7天训练内容&#xff0c;对每一部分需要掌握的数据结构与算法做了总结。现在我把这些题目放在一起&…

小程序·云开发实战 - 迷你微博

0. 前言 本文将手把手教你如何写出迷你版微博的一行行代码&#xff0c;迷你版微博包含以下功能&#xff1a; Feed 流&#xff1a;关注动态、所有动态发送图文动态搜索用户关注系统点赞动态个人主页使用到的云开发能力&#xff1a; 云数据库云存储云函数云调用没错&#xff0c;几…

看看自己08年的基金是否能赚钱

你的机器人已通过审核&#xff0c; 机器人名称&#xff1a;天才小猪仔-基金定投 机器人帐号&#xff1a;sharetop.cnhotmail.com 机器人地址&#xff1a; http://contest.xiaoi.com/listRobot.do?actionshowDetail&id61 欢迎进入 http://contest.xiaoi.com 为你的机器人…

spring mvc学习(60):ssm项目整合

SSM整合 建立springmvc项目&#xff0c;先跑起来&#xff0c;再整合spring和mybatis 一.SpringMVC建立 1.新建maven工程&#xff0c;安装tomcat 2.导入pom <!-- springmvc --><dependency><groupId>org.springframework</groupId><artifactId>…

回溯算法归纳

回溯算法解题思路回溯的两种思路题目描述按照思路1解决按思路2解决回溯的两种思路 看不同的解题方法&#xff0c;形成不同的思维。 先说结论。回溯解题思路1&#xff1a;是对可选择每个元素&#xff0c;采取不选择、选择两种策略&#xff0c;不断递归下去。最近看花花酱的视频…

Des与3Des加密解密

/// <summary>/// Des和3Des算法/// </summary>public class Des{/// <summary>/// Des加密/// </summary>/// <param name"pToEncrypt">明文</param>/// <param name"sKey">密钥</param>/// <returns…

Javascript中Date对象的使用

JavaScript 没有一个基本的日期数据类型&#xff0c;所以我们只能显式地创建Date对象。我们创建新的Date对象和创建String对象的方式是一样的&#xff0c;使用关键字new和Date构造函数。下面这行创建了一个包含当前日期和实践的Date对象&#xff1a;var todaysDate new Date()…

数据结构与算法总结(完结)

极客时间算法学习之后开始跟着花花酱刷题。大概从4月份开始的。从今天开始&#xff08;2020-8-24&#xff09;开始做总结&#xff0c;复习一下已经刷过的题目。到目前为止leetcode刷题323道。 2020/8/24 完成题目整理&#xff0c;下一步是将每个题目都加上超链接。这个超链接尽…

mybatis学习(1):【持久化框架】Mybatis简介与原理

从这篇博文开始我们学习一下Mybatis&#xff0c;希望大家提出宝贵的建议。 什么是Mybatis MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code&#xff0c;并且改名为MyBatis 。iBATIS一词来源于“internet”和“abati…

UML类图解义

小菜&#xff1a;“对了&#xff0c;我时常在一些技术书中看到这些类图表示&#xff0c;简单的还看得懂&#xff0c;有些标记我很容易混淆。要不你给我讲讲吧。” 大鸟&#xff1a;“这个其实多看多用就熟悉了。我给你举一个例子&#xff0c;来看这样一幅图&#xff0c;其中就包…

mybatis学习(2):基本设置和核心配置

1创建一个简单的java项目 2导入jar包 建立一个lib包 链接&#xff1a;https://pan.baidu.com/s/1eJ7xXF2qvUbgde2T--Sphg 提取码&#xff1a;3bgy 加入junit的包 右键项目---build path---add library 4导入配置文件 log4j.properties ### ### log4j.rootLogger ERROR,s…

laravel框架的数据库链接

刚才配置了数据库链接代码之后发现怎么也连不上&#xff0c;是因为有两个文件 .env和.envexample文件&#xff0c;注意配置参数要在.env文件里面&#xff0c;比如我用mysql的话配置.env里 这么一段&#xff1a; DB_CONNECTIONmysqlDB_HOSTlocalhostDB_PORT8889DB_DATABASEshopD…

2899紫金矿业和1862澳华黄金一直都是我的重仓品种啊

2899紫金矿业和1862澳华黄金一直都是我的重仓品种啊2899紫金矿业和1862澳华黄金一直都是我的重仓品种啊http://cache.tianya.cn/publicforum/content/develop/1/135210.shtml 转载于:https://www.cnblogs.com/cy163/archive/2008/02/17/1071029.html