当前位置: 首页 > article >正文

VS2019 MFC CEF(Chrome)集成实战:从环境配置到核心功能实现(含源码解析)

1. 为什么要在MFC中集成CEF十年前我刚接触MFC开发时最头疼的就是界面美化问题。传统的GDI绘图方式要实现一个圆角按钮都得折腾半天更别说复杂的动态效果了。直到发现CEFChromium Embedded Framework这个神器才真正解决了MFC应用的现代化问题。CEF本质上是一个将Chromium浏览器引擎嵌入到原生应用的框架。想象一下你的MFC程序突然拥有了和Chrome浏览器完全一致的网页渲染能力这意味着可以直接用HTML5CSS3开发炫酷界面完美支持JavaScript和WebGL等现代技术能加载任何现代网页包括在线地图、视频等实现MFC与Web页面的双向通信我在多个工业控制项目中采用这种方案后开发效率提升了至少3倍。比如最近做的SCADA系统监控界面全部用Vue开发通过CEF嵌入到MFC框架中既保持了传统桌面应用的稳定性又获得了现代Web的灵活性。2. 环境搭建避坑指南2.1 获取CEF二进制包首先到CEF官网下载对应版本的二进制包。这里有个大坑一定要选择minimal distribution版本完整版有300MB而精简版只有40MB左右对桌面应用完全够用。我推荐使用CEF 92版本92.0.27这个版本比较稳定。下载后你会得到一个类似cef_binary_92.0.27_windows32.zip的文件包解压后目录结构如下cef_binary_92.0.27_windows32/ ├── include/ # 头文件 ├── Debug/ # Debug版库文件 ├── Release/ # Release版库文件 ├── Resources/ # 资源文件 └── libcef_dll/ # 包装库源码2.2 创建MFC项目结构在VS2019中新建一个MFC对话框项目后建议按以下方式组织目录YourProject/ ├── cef/ # CEF相关文件 │ ├── bin/ # 运行时文件 │ │ ├── Debug/ │ │ └── Release/ │ ├── lib/ # 库文件 │ └── src/ # 源码和头文件 ├── res/ # 资源文件 └── YourProject/ # 项目源码把下载的CEF文件中include/复制到cef/src/Debug/下的.lib文件复制到cef/lib/Debug/Release/下的.lib文件复制到cef/lib/Release/Resources/下的所有文件复制到cef/bin/Debug/和cef/bin/Release/2.3 项目配置关键点在VS2019的项目属性中这些配置最容易出错运行库设置Debug配置/MTdRelease配置/MT这个必须和CEF的编译选项一致否则会引发LNK2038链接错误。预处理器定义 在Debug配置中必须添加_HAS_ITERATOR_DEBUGGING0 _ITERATOR_DEBUG_LEVEL0清单文件 在项目根目录创建my.manifest文件内容如下?xml version1.0 encodingutf-8? assembly xmlnsurn:schemas-microsoft-com:asm.v1 manifestVersion1.0 compatibility xmlnsurn:schemas-microsoft-com:compatibility.v1 application supportedOS Id{1f676c76-80e1-4239-95bb-83d0f6d0da78}/ supportedOS Id{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}/ /application /compatibility /assembly然后在项目属性中引用这个文件否则会出现白屏问题。3. 核心功能实现3.1 初始化CEF环境CEF的初始化必须在程序启动时完成。在CYourApp::InitInstance()中添加CefMainArgs main_args(m_hInstance); CefRefPtrCCefBrowserApp app(new CCefBrowserApp); // 检查是否子进程 int exit_code CefExecuteProcess(main_args, nullptr, nullptr); if (exit_code 0) { return exit_code; } // 主进程初始化 CefSettings settings; settings.no_sandbox true; // 关闭沙盒简化部署 settings.multi_threaded_message_loop true; // 使用多线程消息循环 CefInitialize(main_args, settings, app.get(), nullptr);记得在程序退出时清理CefQuitMessageLoop(); CefShutdown();3.2 创建浏览器控件在对话框类中添加浏览器控件在资源编辑器中添加一个Picture ControlID设为IDC_BROWSER在OnInitDialog()中创建浏览器CRect rect; GetDlgItem(IDC_BROWSER)-GetWindowRect(rect); ScreenToClient(rect); CefWindowInfo window_info; window_info.SetAsChild(m_hWnd, rect); CefBrowserSettings browser_settings; CefRefPtrCCefBrowserHandler handler(new CCefBrowserHandler()); CefBrowserHost::CreateBrowser(window_info, handler, https://www.example.com, browser_settings, nullptr, nullptr);3.3 实现浏览器功能创建一个CCefBrowserHandler类来处理浏览器事件class CCefBrowserHandler : public CefClient, public CefDisplayHandler, public CefLifeSpanHandler { public: // 必须实现的接口 CefRefPtrCefDisplayHandler GetDisplayHandler() override { return this; } CefRefPtrCefLifeSpanHandler GetLifeSpanHandler() override { return this; } // 页面加载完成回调 void OnLoadEnd(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, int httpStatusCode) override { // 可以在这里执行JS脚本 frame-ExecuteJavaScript(alert(页面加载完成!);, frame-GetURL(), 0); } IMPLEMENT_REFCOUNTING(CCefBrowserHandler); };4. 高级功能实现4.1 MFC与JavaScript通信实现双向通信需要扩展CCefBrowserHandler// 添加CefRenderProcessHandler接口 class CCefBrowserHandler : public CefClient, public CefRenderProcessHandler { public: // 注册JS扩展 void OnWebKitInitialized() override { CefRegisterExtension(example, var app; if (!app) app {}; app.sendToHost function(message) { native function sendToHost(); return sendToHost(message); };, new CefAppExtensionHandler(this)); } // 处理JS调用 bool OnProcessMessageReceived(CefRefPtrCefBrowser browser, CefRefPtrCefFrame frame, CefProcessId source_process, CefRefPtrCefProcessMessage message) override { if (message-GetName() js_message) { CefString msg message-GetArgumentList()-GetString(0); // 处理来自JS的消息 return true; } return false; } };在MFC中调用JS代码CefRefPtrCefBrowser browser /* 获取浏览器实例 */; CefRefPtrCefFrame frame browser-GetMainFrame(); frame-ExecuteJavaScript(alert(来自MFC的消息);, frame-GetURL(), 0);4.2 自适应窗口大小在对话框的OnSize()中调整浏览器控件void CYourDialog::OnSize(UINT nType, int cx, int cy) { CDialogEx::OnSize(nType, cx, cy); if (GetDlgItem(IDC_BROWSER)) { CRect rect; GetClientRect(rect); GetDlgItem(IDC_BROWSER)-MoveWindow(rect); // 通知浏览器调整大小 if (m_browser) { m_browser-GetHost()-WasResized(); } } }5. 常见问题解决方案白屏问题检查清单文件是否正确配置确保CEF资源文件特别是icudtl.dat在可执行文件目录下确认没有杀毒软件拦截CEF进程崩溃问题确保所有CEF对象都在UI线程访问使用CEF_REQUIRE_UI_THREAD()宏检查线程避免在析构函数中直接操作CEF对象内存泄漏检测 CEF默认会输出内存泄漏信息到调试窗口。如果需要更详细的检测可以重写CefApp::OnBeforeCommandLineProcessingvoid CCefBrowserApp::OnBeforeCommandLineProcessing( const CefString process_type, CefRefPtrCefCommandLine command_line) { command_line-AppendSwitch(enable-logging); command_line-AppendSwitchWithValue(log-severity, verbose); }6. 项目源码解析完整的项目源码包含以下关键部分CCefBrowserApp继承CefApp和CefBrowserProcessHandler处理进程生命周期和全局设置CCefBrowserHandler实现各种CEF接口CefClient、CefLifeSpanHandler等处理浏览器事件和消息主对话框类管理浏览器控件实现与JavaScript的交互处理窗口大小变化资源文件CEF必需的DLL和资源文件自定义清单文件在实际项目中我通常会将这些功能封装成独立的CefBrowserCtrl控件类方便在不同对话框中复用。这个控件提供以下接口class CCefBrowserCtrl { public: BOOL Create(CWnd* pParent, const CRect rect); // 创建浏览器控件 void Navigate(LPCTSTR lpszUrl); // 导航到指定URL void ExecuteJavaScript(LPCTSTR lpszCode); // 执行JS代码 void RegisterJSFunction(LPCTSTR lpszName); // 注册JS函数 };

相关文章:

VS2019 MFC CEF(Chrome)集成实战:从环境配置到核心功能实现(含源码解析)

1. 为什么要在MFC中集成CEF? 十年前我刚接触MFC开发时,最头疼的就是界面美化问题。传统的GDI绘图方式要实现一个圆角按钮都得折腾半天,更别说复杂的动态效果了。直到发现CEF(Chromium Embedded Framework)这个神器&…...

VLA 边缘感知决策:Deepoc 开发板强化机械狗灾后救援自主作业能力

在地震废墟、火灾现场、洪水灾区等无定位、弱通信、地形极端的灾后救援场景中,四足机器人的自主作业能力仍存在明显技术瓶颈。传统方案高度依赖预建地图与稳定通信,在环境坍塌、结构非结构化的区域易出现定位漂移、路径失效等问题,难以支撑救…...

BiliDownload终极指南:三步快速实现无水印B站视频下载

BiliDownload终极指南:三步快速实现无水印B站视频下载 【免费下载链接】BiliDownload B站视频下载工具 项目地址: https://gitcode.com/gh_mirrors/bil/BiliDownload BiliDownload是一款免费开源的B站视频下载工具,通过调用B站WEB端与TV端API&…...

基于滑膜控制的3车协同自适应巡航控制技术:理论与实践的全面解析

基于滑膜控制smc的3辆协同自适应巡航控制,上层滑膜控制器产生期望加速度,下层通过油门和刹车控制车速,实现自适应巡航控制。 个人觉得从结果图中看出基于滑膜控制的效果非常好,不亚于模型预测控制mpc!!&…...

Spotify广告拦截终极方案:BlockTheSpot深度技术解析与实战指南

Spotify广告拦截终极方案:BlockTheSpot深度技术解析与实战指南 【免费下载链接】BlockTheSpot Video, audio & banner adblock/skip for Spotify 项目地址: https://gitcode.com/gh_mirrors/bl/BlockTheSpot 在享受Spotify免费音乐服务时,无休…...

3分钟掌握阅读APP书源导入:告别书荒,开启全网小说自由阅读之旅

3分钟掌握阅读APP书源导入:告别书荒,开启全网小说自由阅读之旅 【免费下载链接】Yuedu 📚「阅读」自用书源分享 项目地址: https://gitcode.com/gh_mirrors/yu/Yuedu 你是否遇到过这样的情况:深夜追更时突然提示"书源…...

常用运放电路

一:运放核心基础1.核心定律虚断:运放两个输入端的输入电流≈0(相当于开路,电流只走反馈电阻)。虚短:运放线性区(有负反馈)时,同相端电压≈反相端电压(V V-&a…...

C++链表:从原理到实战

C链表详解链表是一种常见的数据结构,用于存储一系列元素。与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针链接在一起。链表由节点组成,每个节点包含数据和指向下一个节点的指针。链表的基本概念链表由多个节点组成&…...

ESP32-WROVER-E/IE模组硬件选型与外围电路设计实战

1. ESP32-WROVER-E与ESP32-WROVER-IE模组选型指南 第一次接触ESP32-WROVER系列模组时,很多人会被型号后缀搞晕。其实区分E和IE版本只需要记住一个关键点:字母"I"代表外部天线接口。ESP32-WROVER-IE模组预留了IPEX天线座,而ESP32-WR…...

Python基础:字符串的定义、拼接与转义字符使用

Python基础:字符串的定义、拼接与转义字符使用📚 本章学习目标:深入理解字符串的定义、拼接与转义字符使用的核心概念与实践方法,掌握关键技术要点,了解实际应用场景与最佳实践。本文属于《Python从入门到精通教程》Py…...

多智能体市场(Multi-Agent Marketplace):未来的应用分发新形态

多智能体市场(Multi-Agent Marketplace):未来的应用分发新形态 引言:迎接智能体经济的新纪元 在技术发展的历史长河中,我们见证了多个应用分发范式的革命性变迁:从早期的软件商店到移动应用生态,再到如今的SaaS平台。每一次变革都重新定义了软件的创建、分发和消费方式…...

用Dex-Net 2.0数据集训练自己的抓取检测模型:一个绕过数据瓶颈的实战思路

利用Dex-Net 2.0数据集突破机器人抓取研究的数据困境:轻量化实战指南 在机器人抓取研究领域,数据匮乏往往是制约个人研究者和小型团队的最大瓶颈。当大型科技公司能够投入数百万美元构建专用数据集时,独立研究者该如何在有限资源下开展前沿研…...

Boss-Key:Windows终极隐私保护工具,一键隐藏窗口的办公神器

Boss-Key:Windows终极隐私保护工具,一键隐藏窗口的办公神器 【免费下载链接】Boss-Key 老板来了?快用Boss-Key老板键一键隐藏静音当前窗口!上班摸鱼必备神器 项目地址: https://gitcode.com/gh_mirrors/bo/Boss-Key 在当今…...

LSTM实战:遗忘门、输入门与输出门解决长期依赖

LSTM实战:遗忘门、输入门与输出门解决长期依赖 本文是上篇《Word2Vec与CBOW算法实战》的续篇。上篇解决了"如何用词向量表示词语"的问题,但还有一个关键问题没解决:如何让模型理解前后词语之间的关联关系? 这就是 RNN 到…...

4月18日腾讯云「龙虾公开课」落地合肥!免费线下AI实战课,还有限定周边等你拿

合肥线下:免费AI实战课的吸引力4月18日,腾讯云开发者社区「龙虾公开课」将在合肥高新区中安创谷科技园二期H1栋国际会客厅举办。此次活动提供免费的线下AI Agent实战课,即使是零基础的参与者也能参与。课程涵盖1对1装机指导、现场实操工坊&am…...

工业物联网设备接入终极方案:Apache PLC4X统一协议访问平台

工业物联网设备接入终极方案:Apache PLC4X统一协议访问平台 【免费下载链接】plc4x PLC4X The Industrial IoT adapter 项目地址: https://gitcode.com/gh_mirrors/pl/plc4x 在智能制造和工业4.0时代,工厂车间里往往混杂着西门子、施耐德、三菱、…...

PyQt5入门实战:安装、QtDesigner设计与PyUIC转换完整指南

PyQt5 入门实战:安装、QtDesigner 设计与 PyUIC 转换完整指南环境说明:Python 3.9 PyQt5 5.15.4 PyCharm(Community/Professional 均适用)一、什么是 PyQt5? PyQt5 是 Qt5 框架的 Python 绑定,由 Riverba…...

别只盯着内核!RT-Thread v5.2.2里这些开发工具和测试框架的更新,同样能提升你的效率

别只盯着内核!RT-Thread v5.2.2里这些开发工具和测试框架的更新,同样能提升你的效率 当大多数开发者都在关注RT-Thread v5.2.2的内核优化和驱动升级时,那些隐藏在更新日志后半部分的工具链改进,正在悄然重塑嵌入式开发的效率边界。…...

Python数据科学实战:list、numpy与torch.tensor高效互转指南

1. 为什么需要掌握数据结构互转技巧 在数据科学和机器学习项目中,数据格式的混乱往往是bug的主要来源之一。我遇到过太多这样的情况:模型训练时突然报错,排查半天发现是输入数据的格式不对;或者在不同库之间传递数据时&#xff0c…...

生成式AI时代的产品创新:以AI Agent为核心功能的下一代APP设计

生成式AI时代的产品创新:以AI Agent为核心功能的下一代APP设计 1. 引入与连接 1.1 一个引人入胜的未来场景 想象一下,2025年的一个普通早晨: 你的手机闹钟响起,但这不是预设好的固定时间,而是你的"私人生活助理"AI Agent根据你的睡眠质量、当天日程和天气情…...

别再到处找下载链接了!Linux系统压力测试工具stress和stress-ng最新稳定版安装包获取指南

Linux系统压力测试工具stress与stress-ng权威获取指南 在Linux系统运维和性能调优领域,压力测试是不可或缺的环节。作为最常用的两款开源压测工具,stress和stress-ng能够模拟CPU、内存、IO等多种资源的高负载场景,帮助开发者验证系统稳定性。…...

5分钟搞定!Android Studio中文界面完整汉化终极指南

5分钟搞定!Android Studio中文界面完整汉化终极指南 【免费下载链接】AndroidStudioChineseLanguagePack AndroidStudio中文插件(官方修改版本) 项目地址: https://gitcode.com/gh_mirrors/an/AndroidStudioChineseLanguagePack 还在为Android St…...

如何在3分钟内免费获得Apex Legends终极压枪助手

如何在3分钟内免费获得Apex Legends终极压枪助手 【免费下载链接】Apex-NoRecoil-2021 Scripts to reduce recoil for Apex Legends. (auto weapon detection, support multiple resolutions) 项目地址: https://gitcode.com/gh_mirrors/ap/Apex-NoRecoil-2021 还在为Ap…...

从I2C波形到数据校验:用逻辑分析仪深度调试STM32驱动SHT30的全过程

从I2C波形到数据校验:用逻辑分析仪深度调试STM32驱动SHT30的全过程 当你的STM32代码无法正确读取SHT30温湿度数据时,示波器或逻辑分析仪捕获的I2C波形往往比串口打印的调试信息更有说服力。本文将带你走进硬件调试的真实战场,通过分析四种典型…...

从代码审计到漏洞挖掘:深度解析Gerapy项目管理模块的RCE漏洞(CVE-2021-32849)

从代码审计到漏洞挖掘:深度解析Gerapy项目管理模块的RCE漏洞(CVE-2021-32849) 在分布式爬虫管理领域,Gerapy作为整合Scrapy、Django等技术栈的解决方案,其安全性直接影响企业数据采集业务的稳定性。2021年曝光的CVE-20…...

ST MCSDK V6.2.0实战:手把手教你配置HSO-ST观测器,体验无感电机控制的‘快准稳’

ST MCSDK V6.2.0深度实战:HSO-ST观测器配置与无感控制优化指南 在电机控制领域,实现高精度、快速响应的无感控制一直是工程师们追求的目标。ST最新发布的MCSDK V6.2.0软件包中引入的HSO-ST(High Sensitivity Observer)观测器技术,为这一目标提…...

Multisim14仿真进阶:单管共射放大电路参数扫描与性能优化实战

1. 单管共射放大电路基础与Multisim14环境搭建 单管共射放大电路是模拟电路学习的经典案例,它就像电子世界的"扩音器",能把微弱的电信号放大到我们需要的强度。在Multisim14这个电子工程师的"虚拟实验室"里,我们可以安全…...

深入Linux内核:cgroup v2如何用单一层级解决容器资源管理的世纪难题?

Linux内核革命:cgroup v2如何用单一层级重塑容器资源管理 1. 从混乱到秩序:cgroup的演进之路 在云计算和容器化技术蓬勃发展的今天,Linux内核中的控制组(cgroup)技术已成为资源隔离和管理的基石。然而,cgro…...

052篇:NLP文本分类:判断邮件是投诉还是咨询

1. 前言 在RPA自动化中,经常会遇到需要理解文本内容的场景: 客户发来的邮件是投诉还是咨询? 工单描述属于哪个部门处理? 用户评价是正面还是负面? NLP(自然语言处理)可以自动分析文本,判断类别和情感。本文以百度NLP为例,讲解如何调用情感分析和自定义分类接口,并将…...

三步解除极域电子教室控制:JiYuTrainer让你重获电脑操作自由

三步解除极域电子教室控制:JiYuTrainer让你重获电脑操作自由 【免费下载链接】JiYuTrainer 极域电子教室防控制软件, StudenMain.exe 破解 项目地址: https://gitcode.com/gh_mirrors/ji/JiYuTrainer 还在为课堂上被老师全屏控制电脑而束手无策吗&#xff1f…...