十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

CEF4Delphi实践:Delphi桌面程序嵌入Chromium内核指南

CEF4Delphi实践:Delphi桌面程序嵌入Chromium内核指南 简介CEF4Delphi 组件 86.0.23.0 版是一套面向 Delphi 与 Lazarus 开发者的开源浏览器组件包将 Chromium 内核封装成可复用的可视化组件该版本随附 win32 与 win64 支持库开发者无需自行编译即可把现代浏览器能力嵌入桌面应用程序适合需要内嵌网页、地图、富文本编辑、模板渲染等功能的项目团队或个人开发者。压缩包共包含 1383 个文件整体约 143.74MB内部以 pas 源文件、dcu 编译单元为组件核心同时提供 dproj、dpr 工程文件便于在 IDE 中打开安装与二次开发dll 动态库和 pak 数据文件覆盖不同平台的运行支撑bat 与 inc 辅助脚本用于自动化构建和环境配置结构清晰便于按需提取。已有 1282 人学习下载。获取这份资源后开发者可获得完整组件源码、对应版本支持库、安装工程与配置脚本按标准 Library 路径配置或编译工程即可完成注册从而在 Delphi 应用中直接调用浏览器内核能力显著降低底层集成与多平台适配的复杂度。 做Delphi桌面开发的人估计都撞过同一个南墙程序里嵌的TWebBrowser还是IE内核客户那边网页稍微用点现代样式就白屏、错位、弹脚本错误一个简单的登录页都能卡半天。CEF4Delphi就是这个死局的解法它把Chromium Embedded FrameworkCEF完整封装成Delphi可以直接调用的组件让桌面程序拥有和Chrome一致的内核级渲染能力。这篇文章聊的是我项目中实际在用的86.0.23.0版本带全套支持库的那种我会把选型理由、支持库明细、部署步骤和真实踩坑一起铺开讲。适合正在用旧版组件、或者头一回给Delphi工程嵌入浏览器内核的开发者按这篇文章走一遍基本能跑通第一个带现代网页的桌面程序。1. 为什么是CEF4Delphi桌面程序嵌入浏览器内核的选型复盘1.1 三种主流方案横评做嵌入式浏览器绕不开三条路。第一是Delphi自带的TWebBrowser底层是IE内核稳定是真稳定但只能处理老网页CSS Grid、ES6、WebGL这些基本不用想还经常被Windows更新和IE退役搞得行为漂移。第二是Edge WebView2微软官方支持Chromium内核但部署时要在目标机器上预装WebView2 Runtime在一些完全离线的生产和办公环境里这一步就卡死了。第三就是CEF4Delphi直接把Chromium的完整运行库带在程序目录里不依赖目标机器预装任何东西离线环境照跑版本也可固定不会“下次开机突然变了个样子”。我接触到的使用场景里选CEF4Delphi的往往是军工、电力、医保、制造业这类没法联网、又不能随便升级系统的行业。这些环境里有个很硬的需求程序拿到一台旧电脑上放进去就能跑不装任何前置依赖。CEF4Delphi的自包含特性在这类环境下是最关键的胜负手。1.2 86.0.23.0这个版本为什么说是成熟期版本CEF4Delphi的版本号是跟着Chromium走的86.0.23.0对应的是Chromium 86内核后面的0.23.0是CEF4Delphi自己的发布递增号。这个版本不是最新但属于一个很成熟的阶段。我自己的体会是嵌入浏览器这种活儿真不一定越新越好。新版本Chromium对新特性的支持确实好但代价也很明显DLL体积越来越大、内存占用越来越高、对GPU和系统环境的容忍度越来越低放在Win7的老工控机上可能直接起不来。86这个节点CEF4Delphi的VCL封装已经非常稳定支持Delphi 10.3到Delphi 11的大多数版本编译配置也不复杂。我在一个长期维护的客户项目里从80版本升到86主要就是为了解决一个页面兼容性问题升级过程前后花了不到一天收益非常明显。2. 86.0.23.0版支持库全解这些DLL到底都是干什么的2.1 支持库里每一类文件的职责“带支持库”这个说法在CEF4Delphi里通常指发布包自带了完整可运行的CEF二进制文件不需要你再去单独下载几十MB的CEF压缩包。把这些文件解压到exe同目录之前最好先搞清楚每个文件是干什么的排错的时候思路会清楚很多。文件/目录作用说明libcef.dllCEF核心库Chromium内核主体体积最大通常100MB以上缺它程序直接起不来chrome_elf.dll崩溃处理与信号拦截少了它某些系统上会闪退icudtl.datICU国际化数据处理编码、排序等路径错了页面可能乱码或白屏v8_context_snapshot.binV8引擎上下文快照加速JS引擎启动natives_blob.binV8内置函数快照同样关涉JS引擎初始化snapshot_blob.binV8启动快照部分版本存在缺失会报错d3dcompiler_47.dllDirect3D着色器编译器老系统上特别容易缺导致GPU进程崩溃libEGL.dll / libGLESv2.dllANGLE图形抽象层把OpenGL ES转成D3D调用显卡兼容性靠它cef.pak / devtools_resources.pakChromium资源包内置页面和开发者工具资源locales目录多语言翻译文件没有它界面文字会变成方块vk_swiftshader.dll软件渲染后备GPU不可用时兜底新版本CEF一般都有2.2 支持库的部署方式这些文件不是随便扔进某个子目录就能用的。默认情况下CEF查找资源是按libcef.dll所在目录为基准的最稳妥的做法就是全部解压到exe同一级目录一个子目录都不建。如果你非要分开放那就必须在初始化时手动设置FrameworkDirPath、ResourcesDirPath、LocalesDirPath这些路径但说实话在项目里我从来没这么干过放同目录是最省心的。还有一个特别容易翻车的地方32位和64位支持库不能混用。Delphi Win32程序要用32位的libcef.dllWin64程序要用64位的你从两个压缩包里各拼一半大概率跑起来就各种诡异崩溃。正式发布的包建议用7z压缩分发90多MB的目录能压到40MB左右拷贝也方便。3. 环境配置与首次跑通从拿到包到第一个页面3.1 Delphi端的依赖接入先说Delphi侧的配置。拿到CEF4Delphi源码后最简单的方式不是去安装什么第三方包而是把源码目录加入IDE的Library Path。菜单Tools Options Delphi Options Library在Library path里把CEF4Delphi的source目录追加进去。这样在uses里直接引用uCEFInterfaces、uCEFApplicationCore、uCEFChromiumWindow这些单元就够了。好处是编译时不需要额外打包调试也方便可以直接定位到CEF4Delphi源码里去看问题。坏处是你升级CEF4Delphi版本时得手动清理一下缓存重新编译。我个人的建议是正式项目用Library Path方式别用BPL打包打包运行时组件反而容易造成VCL版本冲突。3.2 最小可运行工程创建工程时要注意一个点CEF4Delphi要求在创建主窗体之前初始化CEF进程入口不然子进程工作不正常。这里面有个容易被新手忽略的细节工程主文件里的代码和你平时写的普通VCL程序有一点不同要先初始化GlobalCEFApp再判断是否继续主流程。program WebApp; uses Vcl.Forms, uCEFApplicationCore, MainForm in MainForm.pas {Form1}; {$R *.res} var MainForm: TForm1; // 声明避免启动窗口冲突 begin // CEF初始化必须在Application.Initialize之前完成 GlobalCEFApp : TCefApplicationCore.Create; GlobalCEFApp.FrameworkDirPath : ExtractFilePath(Application.ExeName); GlobalCEFApp.ResourcesDirPath : ExtractFilePath(Application.ExeName); GlobalCEFApp.LocalesDirPath : ExtractFilePath(Application.ExeName) Locales; GlobalCEFApp.cache : ExtractFilePath(Application.ExeName) Cache; if GlobalCEFApp.StartMainProcess then begin Application.Initialize; Application.CreateForm(TForm1, MainForm); Application.Run; end; GlobalCEFApp.Free; GlobalCEFApp : nil; end.在MainForm上放一个TChromiumWindow设置好OnAfterCreated事件然后调用LoadURL加载页面。你也可以放一个TChromium控件手动做窗体嵌入但TChromiumWindow封装得更完整对VCL窗体来说最省事。第一次跑通看到页面加载出来也就二十分钟的事。注意一个细节MainForm里的Application.CreateForm参数类型是TFormClass如果你的工程里Form1是TForm1类型这段代码是没问题的。工程选项里Main form不用特意设置因为这是手工写在dpr里的。3.3 进程模型和正式分发CEF是多进程架构跑起来之后Task Manager里会多出一堆cef子进程有GPU进程、渲染进程、网络进程这是正常现象不要当成病毒或泄漏。要验证是不是内存泄漏看程序退出后进程是否全部消失。正式分发时还有几个优化点缓存目录建议指定到exe目录下的Cache子目录避免每次启动都重建缓存、拖慢加载。开发模式下CEF会把日志打到本地正式环境记得把LogSeverity调成LOGSEVERITY_DISABLE不然磁盘上会积累日志文件。如果目标机器全是老显卡初始化时顺便加几个开关比如禁用GPU加速效果立竿见影。4. 常见问题与排查实战我踩过的那些坑4.1 启动就报“找不到libcef.dll”或“应用程序无法启动”这大概是出现频率最高的问题。先说结论99%是因为支持库没有放到exe同目录或者32位/64位混了。判断方法是看错误弹窗在什么时候出现——运行瞬间提示基本就是DLL路径问题运行到初始化CEF时报错则要检查locales目录和资源文件是否完整。我见过一种很隐蔽的情况用64位Delphi编译出的程序结果拷的是32位的libcef.dll程序也能启动但一开页面就闪退Windows事件查看器里报“0xc000007b”。这种问题查半天往往是位数不匹配。建议把一份支持库目录固化在工程里每次编译后自动拷贝到输出目录手工拷贝早晚会出错。4.2 页面白屏但程序没有崩溃白屏问题通常在两个方向排查。第一初始化路径不对CEF找不到icudtl.dat或locales目录浏览器引擎已经起来了但没有能力渲染内容。第二GPU进程崩溃了GPU进程一旦启动失败渲染进程就没法工作表现出来就是白屏。我之前在一台老电脑上遇到的就是第二种。排查方式是先把CEF的日志开关打开看自己目录下生成的日志里有没有GPU相关的错误通常能看到“swiftshader”或者“d3d”这类关键词。处理办法也很直接在初始化时加上禁用GPU的开关。GlobalCEFApp.DisableGpu : True; GlobalCEFApp.DisableGpuCompositing : True;对于大多数业务型桌面程序禁用GPU换来的是稳定性和兼容性完全值得。除非你要在页面里跑WebGL或重度CSS3动画否则不建议在生产环境开GPU。4.3 高DPI下字体发虚、网页比例不对很多人第一次把CEF嵌入高分屏程序时都会碰到这个问题整个网页像蒙了一层毛玻璃按钮小到没法点。原因是CEF子进程没开启DPI感知系统用旧的方式做缩放渲染比例就乱了。CEF4Delphi在初始化时可以设置进程DPI感知模式一般配合工程里注释掉的DPI设置一起使用。比较省事的方式是写一个清单文件声明PerMonitorV2感知。改完以后在高分屏上刷新页面字体锐度和控件尺寸马上就正常了。常见场景对应的排查方法我整理成了速查表放到项目维护文档里很实用现象可能原因处理方案启动报0xc000007bDLL位数不匹配确认libcef.dll与编译目标位数一致页面白屏资源路径不对或GPU崩溃检查locales/icudtl.dat路径必要时DisableGpu文字乱码locales目录缺失或损坏恢复完整locales目录保留en-US和zh-CN程序退出后进程残留没有正确释放CEF资源GlobalCEFApp释放顺序要放在窗口销毁后高度屏字体模糊DPI感知未开启配置manifest启用PerMonitorV2点击链接弹出外部浏览器没有设置窗口目标监听BeforeBrowse并控制TargetUrl打开方式4.4 程序退出时卡住或有个别进程残留这个问题属于每个用CEF的人都会碰到一次的级别。CEF的子进程生命周期由主进程管理如果你在主窗口销毁过程中没有先关闭浏览器就容易出现主程序已退出、渲染进程还赖在任务管理器里的情况。CEF4Delphi的常规写法是在MainForm的FormCloseQuery里调用TChromiumWindow的CloseBrowser(True)然后在FormDestroy事件里等CEF资源完全释放。顺序不能反不然主窗口都没了CEF不知道往哪渲染。我把FormCloseQuery事件写成专门的CloseBrowser方法就是把关闭浏览器和销毁窗口两件事明确分开避免GC过度整理导致顺序乱掉。另外程序退出时在Application.Terminate之前做好兜底释放能最大程度避免残留。最后分享一点我的使用体会从旧版TWebBrowser迁到CEF4Delphi是我在好几个项目里做得最果断的一个技术决策。86.0.23.0这个版本用到现在稳定性已经达到生产标准关键点其实不在组件本身而在四个字版本纪律。支持库的DLL别随手升级、别混用位数、别随意调整存放路径这三条记住了能避开一大半线上事故。每次升级CEF4Delphi主版本都建议先在内部机器完整跑一遍“登录-数据加载-分页-打印-退出”全流程再决定要不要推给客户。浏览器内核的东西看着是同一套API底层渲染栈换了页面表现真的会变。这就是我实际操作中最深的感受。本文还有配套的精品资源点击获取
返回列表