Qt中嵌入web网页的几种实现方式

2023-11-03

1、背景

Web网页的界面交互相比较Qt客户端而言有着比较大的优势:更加的多样化和更高的使用便捷性使得我们即使在客户端中也可以考虑将web网页嵌入到客户端的界面当中。如此便能将web的优势和客户端进行结合。更加丰富客户端的界面及功能,以下将介绍几种常见的Qt客户端中嵌入web网页的实现方案和实现步骤。

2、实现方案设计

1、基于Qt自带控件实现

1.1简介

在Qt中,提供了一个用于访问网页的控件(不同的Qt版本对应不同的控件模块),集成了浏览器的webkit内核和google的引擎,不严谨的说,这个控件其实就是一个简易版的浏览器。
Qt5.0~5.4:webkitwidgets模块 - QWebView
Qt5.4之后:webenginewidgets模块 - QWebEngineView
此处我们客户端的qt选型为qt5.9.6,故采用QWebEngineView。

1.2环境配置

Qt5.9.6 + VS2015
注:查看本地的Qt是否有webenginewidgets模块,最简单的方法可右键任意的Qt工程->Qt Project Settings->Qt Modules查看WebEngine Widgets模块是否为灰色,若为灰色则说明未配置此模块,不可选用,需要重装Qt并选中此模块即可。

1.3开发流程

在配置好Qt模块后,便可像普通的button或label一样通过拖ui控件或者直接new的方式来使用。
代码示例:
在这里插入图片描述

效果图展示:
在这里插入图片描述

1.4总结

至此一个简单的Web页面就嵌入成功了,但是基于这种方式实现的浏览器存在弊端:不能对视频进行解码播放,只能查看静态页面。因为Qt组件底部集成的浏览器内核(Chrome浏览器的内核,内核版本由Qt版本决定)是不带解码库的,所以不能进行视频播放。但是可以通过加编译配置重新编译这个控件的源码实现,编译对硬件要求较高,且时间较长。故对于有视频播放功能的需求,不建议作为常规方案采用。

2、嵌入Chrome.exe进程实现

2.1简介

这种实现方式和本地的Chrome浏览器功能上没有差别,在本地浏览器能实现的功能,通过这种方式嵌入到Qt窗口中仍是正常的。实现的本质是从客户端启动浏览器进程并传相应的url及其他参数,再通过Windows的API获取到窗口句柄,进而将窗口句柄进行QWigetde 的转换,实现嵌入。

2.2环境配置

Qt5.9.6 + VS2015

依赖本地的Chrome,所以必须要先下载并安装谷歌浏览器。

2.3开发流程

2.3.1检测浏览器是否存在

检测是否已安装谷歌浏览器,如未安装则提示安装。若已安装则利用Qt的QProcess来启动Chrome.exe并传递浏览器进程需要的参数即可。
启动Chrome.exe需要先获取exe的所在路径,虽然谷歌浏览器的路径是默认安装的,但是在不同的机器上面,路径也是大不相同的。故不能通过遍历某个文件夹或者固定路径来获取,此处可以使用读取注册表的方法获取chrome.exe的所在路径。此处读取的注册表为当前用户(HKEY_CURRENT_USER)但是实际情况下chrome的注册表不一定都在当前用户下,如果当前用户下没有,可继续向本地机器(HKEY_LOCAL_MACHINE)的注册表查询,可自行加判断分支。示例代码如下:
在这里插入图片描述

2.3.2窗口句柄的读取及嵌入

浏览器启动后先要通过spy++工具获取到窗口的类名和标题。spy++的使用可通过打开VS->点击菜单栏的工具->点击spy+±>点击搜索->查找窗口->拖动靶心到想要获取的窗口上即可。
再通过Windows的API:FindWindow(L"Chrome_WidgetWin_1", NULL);来获取浏览器的窗口句柄,这里入参不能为标题名,应通过类名来获取,因为标题名可由不同的地址而变化,标题名一旦变更窗口句柄则获取不到。
句柄获取成功后将句柄转化为QWindow *pWin = QWindow::fromWinId(wid);
最后再创建一个窗口容器:QWidget *pWid = QWidget::createWindowContainer(pWin, this);这个返回的pWid便可通过布局填充到Qt的对应界面中了。
完整代码如下:
在这里插入图片描述

在startDetached启动浏览器后主线程要休眠三秒钟,这个操作不可省略,如果不进行休眠操作则可能会出现嵌入失败的情况。
这里的chrome.exe的进程参数:–chrome-frame为启动的必须参数;-kiosk参数为不显示标题栏启动。其他启动参数可参照以下文档:
https://www.cnblogs.com/yikemogutou/p/12624113.html

2.4总结

这种方式虽然能达到功能完整,但是也存在一定不可控的缺陷:这里是以带参数的方式启动的chrome浏览器,启动时配置为全屏且无标题栏。那么打开客户端后再打开浏览器,打开的浏览器仍会是全屏且无标题栏。若用户先启动了浏览器,再启动客户端。那么客户端的进程参数则不生效,嵌入的web页显示标题栏和地址。这种显然是不合理的。

3、基于Chrome的CEF3实现

3.1简介

CEF全称Chromium Embedded Framework,是一个基于Google Chromium 的开源项目。Google Chromium项目主要是为Google Chrome应用开发的,而CEF的目标则是为第三方应用提供可嵌入浏览器支持。CEF作用是在客户端嵌入网页界面。
CEF本身也是不支持视频播放的,如果需要支持需要对chromium的源码进行重新编译,这里可以参照CEF的官方文档进行编译操作:
https://wiki.hikvision.com.cn/pages/viewpage.action?pageId=168565259
由于编译需要下载CEF及chromium源码,需要稳定的外网环境。我们这里是不具备的。所以这里是在网上找到了一个已经编译好的较符合预期的版本来直接使用。

3.2环境配置

Qt5.9.6 + VS2015

3.3开发流程

3.3.1、cef工程配置编译

下载cef包之后可以看到里面是有一个官网demo的,这里我们可以参照这个示例文档来构建自己的项目
在这里插入图片描述

第一步创建一个空项目,项目下添加以下五个源文件及资源文件,并添加main.cpp,这里以后缀cpp打开异常,统一改为_cpp,后续可自行调整。
在这里插入图片描述
第二步添加包含目录的路径及静态库的包含路径。这里用到以下三个静态库文件,静态库文件在CEF的包里都有包含,由于库文件为debug编译,所以工程也应相配的配置为debug模式
在这里插入图片描述

第三步由于创建项目后的运行时库默认为MDD但是由于静态库文件的运行时库为MTD所以需要同步将项目的运行时库改为MTD
在这里插入图片描述

第四步需要在main.cpp的同级目录下添加CefFrame.manifest文件,并在项目属性的清单输入中添加文件路径
在这里插入图片描述

至此cef的工程文件便能编译过了,接下来就是按照自己的需求做对应的修正即可。

3.3.2、实现流程描述

我这里仍然采用的是启动cef进程的方式,通过启动时传递进程参数(即要访问的url),再通过进程间传参实现对此目的网页的访问。最后再将cef的进程嵌入到客户端中,此处的嵌入方案和之前略有不同,这里如果仍然采用spy++工具和Windows的API获取窗口句柄的方式则不可行,始终获取为空。所以此处采用进程间通信(共享内存)的方式来传递窗口句柄(cef的窗口句柄自己可以获取)。
这里是在客户端启动cef之后进行一个适当的延迟,以保证cef进程已经将窗口句柄的数据写入到共享内存中(当然这里可替换为更好的while循环,直到读到句柄值退出循环体,可作为优化项考虑),最后将句柄转化为QWindow *pWin = QWindow::fromWinId(wid);
最后再创建一个窗口容器:QWidget *pWid = QWidget::createWindowContainer(pWin, this);这个返回的pWid便可通过布局填充到Qt的对应界面中了。部分代码示例如下:
句柄写入到共享内存:
在这里插入图片描述

从共享内存读取句柄:
在这里插入图片描述

3.4总结

这种方案由于在公司内网的限制,不能直接下载chromium及cef的源码进行编译,只能通过网上找已经编译好支持mp4格式的库文件,此处的cef库文件对应的chromium的版本相对较低,解码部分存在限制,不能达到实际的用户使用要求。

4、基于微软的WebView2实现

4.1简介

Microsoft Edge WebView2 控件允许你在本机应用程序中嵌入 Web 技术(HTML、CSS 和 JavaScript)。WebView2 控件使用Microsoft Edge作为呈现引擎在本机应用程序中显示 Web 内容。使用 WebView2,您可以将 Web 代码嵌入到本机应用程序的不同部分,或在单个 WebView 实例中构建所有本机应用程序。
在这里插入图片描述

4.2环境配置

Qt5.9.6 + VS2015
运行环境必须安装WebView2的运行包:MicrosoftEdgeWebView2RuntimeInstallerX64.exe
可到微软官方下载:https://developer.microsoft.com/zh-cn/microsoft-edge/webview2/

4.3开发流程

我们的目的是在qt中嵌入web页面,但目前没有方法可以直接将webview2嵌入到qt的客户端中,所以仍然采用读取进程的窗口句柄方式将整个进程进行嵌入。那么这里将以webview2的win32示例程序为例进行开发讲解。

4.3.1、WebView2工程配置

首先到官网下载对应的webview2的win32示例文档【Win32_GettingStarted】,用vs2015打开后右键单击WebView2GettingStarted 项目->选择Configuration Properties > General
查看对应的目标平台版本【WindowsSDK】和平台工具集是否正确。
在这里插入图片描述

这里的平台版本要选则10.0以上的版本否则会编译时会进行如下报错,如果不是10.0以上版本可自行到Windows官网下载新的SDK即可
在这里插入图片描述

4.3.2、安装 Windows 实现库 (WIL)

配置好SDK后需要配置对应的Windows实现库(WIL),这里在解决方案资源管理器中,右键单击WebView2GettingStarted项目节点,然后选择管理 NuGet 包,在NuGet窗口中,单击“浏览“选项卡,在左上角的搜索栏中,输入Microsoft.Windows.ImplementationLibrary,再选中安装此包即可。
在这里插入图片描述

4.3.3、安装 WebView2 SDK

这一步需要配置webview2的SDK,这里在解决方案资源管理器中,右键单击WebView2GettingStarted项目节点,然后选择管理 NuGet 包,在NuGet窗口中,单击“浏览“选项卡,在左上角的搜索栏中,输入Microsoft.Web.WebView2,再选中安装此包即可。
在这里插入图片描述

4.3.4、实现流程描述

这里采用的是在客户端进程中启动该exe,启动成功后再通过spy++找取窗口句柄来实现的嵌入到客户端的逻辑,故这里仍然通过main函数由客户端向webview2的exe传递最终访问的url,webview的进程获取到url后访问目的网页。这里需要注意一个小细节,由于原代码是以两重lamda表达式的方式实现,所以变量不能直接传递,需要在捕获列表加上此变量,如下:
在这里插入图片描述

至此整个流程便可以实现了,但目前在webview的界面中是有标题栏和按钮的,这是我们不需要的,所以最后一步,我们需要隐藏此标题栏和按钮,只需要一个无边框的界面即可。相关代码如下:
在这里插入图片描述

4.4总结

至此一个简单的基于WebView2控件的程序便成功实现了,可以发现WebView虽然相较于其他的实现方式较为简单且功能及用户体验上更加优秀,但同时这种实现方式也有一个根本的缺点:这种基于Windows的SDK的实现,是无法实现国产化的。所以在无需考虑国产化的情况下,这种方案仍可作为最优方案采用。

3、总结

通过以上四种Qt客户端中嵌入web网页的方案介绍,大致可了解到,在只需要对网页进行显示,无关视频播放的情况下,第一种方案可作为首选;在需要进行视频播放的情况下,且有充分的外网及硬件资源可选则第三种方案,按照自己的需求对CEF及chromium源码进行重编;如需要进行视频播放且没有上述资源时。可选WebView方案进行实现。至于嵌入chrome.exe的实现方案,综合来看不能符合用户的实际使用场景,存在较多不可控因素,因此这里作为反面案例进行概述。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Qt中嵌入web网页的几种实现方式 的相关文章

  • 结构化绑定中缺少类型信息

    我刚刚了解了 C 中的结构化绑定 但有一件事我不喜欢 auto x y some func is that auto正在隐藏类型x and y 我得抬头看看some func的声明来了解类型x and y 或者 我可以写 T1 x T2 y
  • 如何将 std::string& 转换为 C# 引用字符串

    我正在尝试将 C 函数转换为std string参考C 我的 API 如下所示 void GetStringDemo std string str 理想情况下 我希望在 C 中看到类似的东西 void GetStringDemoWrap r
  • STL 迭代器:前缀增量更快? [复制]

    这个问题在这里已经有答案了 可能的重复 C 中的预增量比后增量快 正确吗 如果是 为什么呢 https stackoverflow com questions 2020184 preincrement faster than postinc
  • 在 xaml 中编写嵌套类型时出现设计时错误

    我创建了一个用户控件 它接受枚举类型并将该枚举的值分配给该用户控件中的 ComboBox 控件 很简单 我在数据模板中使用此用户控件 当出现嵌套类型时 问题就来了 我使用这个符号来指定 EnumType x Type myNamespace
  • std::list 线程push_back、front、pop_front

    std list 线程安全吗 我假设不是这样 所以我添加了自己的同步机制 我认为我有正确的术语 但我仍然遇到问题 每个函数都由单独的线程调用 Thread1 不能等待 它必须尽可能快 std list
  • 如何从 Visual Studio 将视图导航到其控制器?

    问题是解决方案资源管理器上有 29 个项目 而且项目同时具有 ASP NET MVC 和 ASP NET Web 表单结构 在MVC部分中 Controller文件夹中有大约100个子文件夹 每个文件夹至少有3 4个控制器 视图完全位于不同
  • 用于 FTP 的文件系统观察器

    我怎样才能实现FileSystemWatcherFTP 位置 在 C 中 这个想法是 每当 FTP 位置添加任何内容时 我都希望将其复制到我的本地计算机 任何想法都会有所帮助 这是我之前问题的后续使用 NET 进行选择性 FTP 下载 ht
  • 需要帮助优化算法 - 两百万以下所有素数的总和

    我正在尝试做一个欧拉计划 http projecteuler net问题 我正在寻找 2 000 000 以下所有素数的总和 这就是我所拥有的 int main int argc char argv unsigned long int su
  • 为什么这个字符串用AesCryptoServiceProvider第二次解密时不相等?

    我在 C VS2012 NET 4 5 中的文本加密和解密方面遇到问题 具体来说 当我加密并随后解密字符串时 输出与输入不同 然而 奇怪的是 如果我复制加密的输出并将其硬编码为字符串文字 解密就会起作用 以下代码示例说明了该问题 我究竟做错
  • 为什么 C# 2.0 之后没有 ISO 或 ECMA 标准化?

    我已经开始学习 C 并正在寻找标准规范 但发现大于 2 0 的 C 版本并未由 ISO 或 ECMA 标准化 或者是我从 Wikipedia 收集到的 这有什么原因吗 因为编写 审查 验证 发布 处理反馈 修订 重新发布等复杂的规范文档需要
  • C 编程:带有数组的函数

    我正在尝试编写一个函数 该函数查找行为 4 列为 4 的二维数组中的最大值 其中二维数组填充有用户输入 我知道我的主要错误是函数中的数组 但我不确定它是什么 如果有人能够找到我出错的地方而不是编写新代码 我将不胜感激 除非我刚去南方 我的尝
  • C# 动态/expando 对象的深度/嵌套/递归合并

    我需要在 C 中 合并 2 个动态对象 我在 stackexchange 上找到的所有内容仅涵盖非递归合并 但我正在寻找能够进行递归或深度合并的东西 非常类似于jQuery 的 extend obj1 obj2 http api jquer
  • 编译时展开 for 循环内的模板参数?

    维基百科 here http en wikipedia org wiki Template metaprogramming Compile time code optimization 给出了 for 循环的编译时展开 我想知道我们是否可以
  • C# 中的 IPC 机制 - 用法和最佳实践

    不久前我在 Win32 代码中使用了 IPC 临界区 事件和信号量 NET环境下场景如何 是否有任何教程解释所有可用选项以及何时使用以及为什么 微软最近在IPC方面的东西是Windows 通信基础 http en wikipedia org
  • 使用特定参数从 SQL 数据库填充组合框

    我在使用参数从 sql server 获取特定值时遇到问题 任何人都可以解释一下为什么它在 winfom 上工作但在 wpf 上不起作用以及我如何修复它 我的代码 private void UpdateItems COMBOBOX1 Ite
  • C++ 中的 include 和 using 命名空间

    用于使用cout 我需要指定两者 include
  • MySQL Connector C/C API - 使用特殊字符进行查询

    我是一个 C 程序 我有一个接受域名参数的函数 void db domains query char name 使用 mysql query 我测试数据库中是否存在域名 如果不是这种情况 我插入新域名 char query 400 spri
  • 类型或命名空间“MyNamespace”不存在等

    我有通常的类型或命名空间名称不存在错误 除了我引用了程序集 using 语句没有显示为不正确 并且我引用的类是公共的 事实上 我在不同的解决方案中引用并使用相同的程序集来执行相同的操作 并且效果很好 顺便说一句 这是VS2010 有人有什么
  • 从 mvc 控制器使用 Web api 控制器操作

    我有两个控制器 一个mvc控制器和一个api控制器 它们都在同一个项目中 HomeController Controller DataController ApiController 如果我想从 HomeController 中使用 Dat
  • 如何确定 CultureInfo 实例是否支持拉丁字符

    是否可以确定是否CultureInfo http msdn microsoft com en us library system globalization cultureinfo aspx我正在使用的实例是否基于拉丁字符集 我相信你可以使

随机推荐

  • Chrome 浏览器的 PDF 插件使用了 Foxit PDF SDK

    Chrome 浏览器的 PDF 插件使用了 Foxit PDF SDK 2010年8月22日 Chrome的内置PDF插件实际上有使用Foxit的PDF SDK 如果你查看这个网页会找到Chromium的一些PDF功能多次用到Foxit的S
  • 【C++】C++的四种类型转换

    文章目录 一 隐式类型转换和显示类型转换 二 C 的四种类型转换 2 1 static cast 相似转化 2 2 reinterpret cast 不同类型转化 2 3 const cast 去除const属性 2 4 dynamic c
  • 利用枚举类型变量求从5种颜色球中取3个不同颜色球的取法

    利用枚举类型变量求从5种颜色球中取3个不同颜色球的取法 C程序设计 第二版 谭浩强 著 11 9 例11 3 口袋里有红 黄 蓝 白 黑5种颜色的若干个 每次从口袋中取出3个球 问得到3种不同色的球的可能取法 输出每种排列的情况 程序 在V
  • CASAIM与南京航空航天大学在自动化叶片曲面分析系统开展合作,推动航空航天发动机零部件自动化3D检测进程

    近期 CASAIM与南京航空航天大学在自动化叶片曲面分析系统展开深入合作 充分发挥双方在航空航天和智能检测领域优势 共同推动航空航天发动机零部件自动化3D检测进程 南京航空航天大学创建于1952年10月 是新中国自己创办的第一批航空高等院校
  • 【python】python求解矩阵的转置(详细讲解)

    博 主 米码收割机 技 能 C Python语言 公众号 测试开发自动化 获取源码 商业合作 荣 誉 阿里云博客专家博主 51CTO技术博主 专 注 专注主流机器人 人工智能等相关领域的开发 测试技术 python求解矩阵的转置 详细讲解
  • pytorch:交换tensor的维度

    在pytorch中 tensor有两个成员函数可以实现维度交换 分别时transpose 和permute transpose 该函数可以交换tensor的任意两个维度 但是该函数一次只有两个参数 即一次只能交换两个维度 import to
  • Solr 检索结果集List<SolrDocument> 转换为指定业务对象总结

    前提说明 从solr结果集中取数据 取到了结果集 但是结果集是一个map 而我想要得到的是一个对象 怎么处理呢 我总计如下三种方法 第一种 solrDocument中提供了一个获取每个field对应值的方法 使用此方法获取所有的field对
  • SWOT、PDCA、SMART……这些对你绝对有用!

    企业的成功一定是有办法的有技巧的 君子性非异也 善假于物也 SWOT分析法帮助企业从四个维度进行综合分析 正确识别自己在市场中所处的地位 扬长避短 聚焦优势资源 在500强工作的员工 SWOT分析是必须具备的技能 特别是做市场的员工 全面的
  • [orin] nvidia orin 上安装 pytorch 和 torchvision 实操

    请看这个博主写的链接 写的非常好 目前我已经安装成功了 不同的是我是在Anaconda虚拟环境中安装的 原博客链接 https blog csdn net beautifulback article details 125717717 这次
  • TEASER-plusplus 安装

    https github com MIT SPARK TEASER plusplus 下载https codeload github com MIT SPARK TEASER plusplus zip v2 0 下载GoogleTest太慢
  • 测试开发概念篇

    目录 前言 几个常见的名词 需求 什么是BUG 测试用例 软件生命周期 开发模型 瀑布模型 螺旋模型 增量和迭代模型 敏捷模型 前言 什么是软件测试 软件测试就是验证产品特性是否满足用户需求 开发软件是为了盈利 必须满足用户才会盈利 测试和
  • LiunxQT开发篇—QT网络编程TCP实现(三)客户端代码

    需要包含三个头文件 include
  • 操作系统——第2章 操作系统用户界面

    目录 第2章 操作系统用户界面 基本概念 系统调用 基本概念 执行过程 第2章 操作系统用户界面 基本概念 一般将计算机系统的用户分为两类 使用和管理计算机应用程序的用户 包括普通用户与管理员用户 程序开发人员 操作系统为第一类用户提供命令
  • 日本半导体行业衰落的原因分析

    90年代初 半导体市场几乎是日本厂商的天下 在排名前十的半导体公司里曾经有6家是日本公司 日本半导体行业衰落的原因分析 那什么导致了今天日本半导体产业的衰落 来看看一些知名调查机构的分析 罪魁祸首1 高层管理人员的傲慢 我们谈过的许多行业观
  • hyperledger fabric Failed to generate orderer genesis block

    当使用configtxgen工具进行生成创世区块和channel tx等时出现错误 具体如下 Generating Orderer Genesis block
  • 解决:Echarts打包后出现白屏

    Echarts打包后出现白屏 原因 这是由于图表的容器节点被移除导致的 即使之后该节点被重新添加 图表所在的节点也已经不存在了 解决方法 利用钩子函数在页面销毁之前将其销毁即可 import onBeforeUnmount from vue
  • QT学习之经典控件源码(如此强大)

    进来好好学习了QT 研究了很多别人的源码 在绘图方面原来QT也是如此强大 源码下载 Files feiyangqingyun myValueControl zip FROM http www cnblogs com feiyangqingy
  • 自动化测试(四):pytest结合allure生成测试报告

    Allure 报告框架的名称 allure noun U 诱惑 魅力 吸引力 文章目录 1 allure下载 2 pytest框架使用allure 3 生成allure报告 1 allure下载 下载前需要先安装JDK 这里可以参考自动化测
  • 图的常用遍历——广度优先遍历和深度优先遍历

    目录 一 遍历图可能遇到的问题 二 图的常用遍历 三 深度优先遍历 DFS 四 广度优先遍历 BFS 一 遍历图可能遇到的问题 图的特点 图中可能存在回路 且图的任一顶点都可能与其它顶点相通 在访问完某个顶点之后可能会沿着某些边又回到了曾经
  • Qt中嵌入web网页的几种实现方式

    1 背景 Web网页的界面交互相比较Qt客户端而言有着比较大的优势 更加的多样化和更高的使用便捷性使得我们即使在客户端中也可以考虑将web网页嵌入到客户端的界面当中 如此便能将web的优势和客户端进行结合 更加丰富客户端的界面及功能 以下将