Delphi 12.3集成HTML Component Library v4.6实战:安装、配置与调优
2026/9/16 7:14:12 网站建设 项目流程

简介:HTML Component Library v4.6 是一套针对 Delphi 平台的 HTML 渲染控件,主要解决 VCL 与 FMX 程序中嵌入网页、解析 HTML/CSS、处理表单交互等问题,支持从 Delphi 5 到 Delphi 11 Alexandria 的多个版本,适合中高级桌面应用开发者选用。包内共 2000 个文件,压缩后 163.33MB,包含 564 个 dcu 编译单元、500 个 hpp 头文件、190 个 obj 文件等核心构建产物;同时带有 dfm 窗体、fmx/lfm 跨平台界面文件,以及 dpk/dproj 工程和 bpl/dcp 运行时包,便于按目标 IDE 快速安装部署。另外还提供 chm、pdf 文档与示例工程,方便查阅接口和上手测试。已有 54 人学习/下载。同时附带授权补丁与 pas 源文件,既能直接集成到开发环境,也可基于源码对组件行为进行定制,有助于缩短 HTML 相关功能的开发周期。

1. Delphi 12.3 上使用 HTML Component Library v4.6,先想清楚它到底解决什么

在 Delphi 12.3 的 IDE 里,HTML Component Library v4.6 是一套老牌第三方控件,提供 THtmlViewer、TFrameViewer 等可直接拖放的 HTML 渲染组件,同时覆盖 VCL 和 FMX,版本跨度从 D5 一直到 D11 Alexandria。很多做 ERP、进销存、报表系统的工程师看到“HTML 控件”,第一反应是挂一个 WebBrowser 或 EdgeBrowser,但 HCL 的做法完全不同:它用自己的解析器和排版引擎画 HTML,不依赖操作系统里的浏览器进程,因此安装体积小、启动快,也几乎没有浏览器版本“昨天能跑今天不能跑”的问题。对正在学习 Delphi 的开发者,以及用 Community Edition 做免费桌面工具的团队来说,这套控件比 CEF 更容易上手,比 WebBrowser 更容易控制渲染结果。本文只讨论 v4.6 的安装、VCL/FMX 接入、参数调优、常见坑和 HTTP 链接拦截技巧;标题里出现的 CRACK 文件不属于开发技术内容,请从正式授权渠道获取组件安装包,后面每个步骤都只针对正规安装包。

2. HTML Component Library v4.6 的架构与选型:为什么它比 Edge/WebView2 更可控

HCL v4.6 最容易被误判的一点是“它到底是不是一个浏览器”。它既不是 Chrome 也不是 IE 的封装,而是一个用 Delphi 对象写出来的 HTML 渲染引擎。理解这一点,才能解释为什么有的人在老电脑上飞一样运行,有的人一接图片多的页面就卡,也才能决定你的项目里哪些页面适合交给它。

2.1 自绘内核与浏览器内核的差异

HCL 在 VCL 版本里通过 GDI 绘制 HTML 元素,在 FMX 版本里则走 TCanvas 绘图栈。它保存的是一棵元素节点树,然后自己决定字体、边框、段落和表格怎么排。这意味着它不启动子进程、不占用 GPU、不要求系统安装 WebView2 Runtime,也没有 ActiveX 注册表残留。代价是它对 JavaScript 的支持很弱,对 CSS3 布局也只能覆盖一部分。拿它渲染完整版的单页后台系统会吃力,拿它渲染订单、发票、邮件模板、帮助文档则非常合适。

下面这张表是我通常会拿给项目组做选型对比的。

对比项HCL v4.6WebView2CEF
内核来源Delphi 自写Edge ChromiumChromium
进程模型单进程多进程多进程
安装依赖需要 Runtime需要大量 DLL
VCL/FMX 原生支持两者都有需要第三方封装需要第三方封装
HTML5/CSS3可用但有限完整完整
内存占用较低较高最高
离线场景优秀依赖缓存依赖缓存

选型时我给的最实用建议是:如果页面固定为项目里自己生成的 HTML,且不需要现代前端框架,HCL 是成本最低的方案;如果页面可能是外部页面、会频繁升级,甚至要用 React 或 Vue,那就别在 HCL 上浪费力气,直接上 WebView2 或 CEF。怕就怕抱着“HCL 能渲染 HTML 就等于能替代浏览器”的预期,最终做到一半发现撑不住。

2.2 VCL 与 FMX 两套分支的设计差异

v4.6 对 VCL 和 FMX 分别维护了单元包,而不是用同一套代码硬兼容。VCL 分支依赖 WinAPI 的句柄和消息传递,所以在 Windows 下控件交互跟原生控件一样自然;FMX 分支则必须用 FMX 的跨平台 TCanvas 去画 Text、Rect 和图片,因此在 Linux、macOS 甚至 Android 上也可以显示 HTML 页面,只是字体获取方式和输入法行为不同。这就带来一个常见的工程结论:老项目升级、保留 Windows 特有能力时优先 VCL;如果是新项目并且明确有多端交付要求,FMX 分支才是正确选择。两者的公开 API 高度接近,但不要在 DFM 里直接混拖 VCL 和 FMX 版本的组件,一个窗体只能使用同一套 UI 框架。

2.3 为什么 D5 到 D11 Alexandria 都要兼容

v4.6 能在这么长的 Delphi 版本区间里通用,核心原因是包内做了大量条件编译。它不是分别维护六七个源码副本,而是在同一个源文件里用编译器版本指令切分差异代码。老项目从 Delphi 7 升到 Delphi 12.3,最常见的工作量不在 HCL,而在你自己的字符串类型和 Windows API 调用。HCL 提供的公共组件通常只依赖很少的底层单元,所以升级时可以直接重用旧代码里的LoadFromStringOnHotSpotClick这些逻辑。

这里也留一个给 Delphi 入门者看的代码片段:在单元头部按编译器版本做初始化,可以避免在旧版本上误用新语法。

unit HtmlInit; interface procedure InitHCLEnvironment; implementation procedure InitHCLEnvironment; begin {$IF CompilerVersion >= 35.0} // Delphi 11 Alexandria 以上才需要执行的额外初始化 {$IFEND} end; end.

这段代码里CompilerVersion是编译器内置的浮点常量,35.0 大致对应 Delphi 11 Alexandria。v4.6 源码里遍布类似的$IF分支,说明它的设计目标就是让同一份用户代码尽量不经修改跨版本编译。我一般在升级前会先确认项目里有没有直接引用 HCL 私有单元,比如从HtmlView内部翻出一些没公开的变量;只要公共 API 用法规范,D5 时代的代码放到 Delphi 12.3 里仍然能编译通过。

3. 在 Delphi 12.3 中安装并注册 HCL v4.6 组件包

安装 HCL v4.6 的流程和装普通第三方控件包基本一致,但因为它是老式组件库,目录里可能同时有 D5、D7、XE、D10、D11 多套包文件,不少人就是栽在“打开一个 .dpk 就编译,结果报版本不匹配”。所以要先看包内目录,再按 Delphi 12.3 对应的包文件走。

3.1 先确认包内目录结构

一个规范发布的 v4.6 包通常包含 source、packages、bin 三类内容。拿到压缩包后,不要先着急双击安装,先看目录结构。

目录/文件作用
Source/VCLVCL 版控件源码,加入 Library Path 后编译期才能找到单元
Source/FMXFMX 版控件源码
Packages/D5-D11各版本.dpk/.bpl工程文件
Bin预编译的 DCU 或包输出
Demo示例工程,安装后对照使用

如果只有源码而没有现成的编译好的包,需要自己在当前 IDE 环境中编译一次。如果包里带有为 Delphi 12.3 单独准备的包文件,直接打开安装。

3.2 设置 Library Path 并编译安装

在 Delphi 12.3 中,先打开Tools > Options > Environment Options > Delphi Options > Library - Win32,把Source\VCLSource\FMX加入 Library Path。这一步不能跳过,因为.dpk编译时只会按项目搜索路径找HtmlViewerHtmlsbs这些基础单元。

接下来在主菜单选择Component > Install Packages,或者直接打开 Packages 目录下的.dpk文件。一个典型操作顺序是:

  1. 在 Project Manager 里找到对应 Delphi 12.3 的 VCL 包,例如D12_HCL_VCL.dpk
  2. 右键选择Compile
  3. 编译成功后右键选择Install
  4. 看到 “Package ... installed” 提示,组件会自动出现在 Tool Palette
  5. 用同样的方法编译并安装 FMX 包

如果不是源码安装,而是已经给您提供了.bpl文件,则在Install Packages对话框中点击Add,选择 VCL 和 FMX 两个.bpl即可。安装完成后,在工具面板搜索FrameViewer,能出现对应图标就算成功。

3.3 用一个最小代码验证安装环境

安装未必等于编译环境可用。Library Path 漏配是新手最常见的坑,表现为打开示例工程时提示找不到HtmlViewer单元。这里给一个独立的验证函数,放在一个空单元里,只测试单元的编译期查找是否正常。

uses HtmlViewer; function HCLCanCreate: string; var V: TFrameViewer; begin V := TFrameViewer.Create(nil); try Result := 'OK: ' + V.ClassName; finally V.Free; end; end;

这个函数能编译通过,说明 Delphi 12.3 的 Library Path 已经正确指向 HCL 源码;调用它并返回OK: TFrameViewer,则说明运行时也会创建组件对象。要注意的是,TFrameViewer.Create(nil)不会自动设置 Parent,也不会显示界面,因此在这个验证函数里不需要窗口句柄。万一编译失败,优先检查Source\VCL是否被加入当前平台为 Win32 的路径里,而不是 Win64 或其他平台。

4. 在 VCL 与 FMX 中嵌入 HTML 的实战配置

安装成功之后,最理想的用法不是把 HTML 塞进 TWebBrowser,而是直接把TFrameViewerTHtmlViewer当作普通控件放到窗体上。下面从 VCL 和 FMX 两个最小工程讲起。

4.1 VCL 最小示例:LoadFromString 显示报表

在 VCL 窗体上放一个 TFrameViewer(IDE 拖拽后默认名是 FrameViewer1),再放一个 TButton。按钮事件里写:

procedure TForm1.ButtonLoadClick(Sender: TObject); begin FrameViewer1.Align := alClient; FrameViewer1.DefFontName := 'Microsoft YaHei'; FrameViewer1.DefFontSize := 10; FrameViewer1.LoadFromString( '<html>' + '<head><meta charset="utf-8"></head>' + '<body>' + '<h2>Delphi 12.3 + HCL v4.6</h2>' + '<p>报表正文区域</p>' + '</body>' + '</html>'); end;

LoadFromString的参数是 Delphi Unicode 字符串,HCL 会直接解析内存中的 HTML,不会发起网络请求。DefFontNameDefFontSize决定了 HTML 里没有显式写字体样式的那些文字怎么显示。Windows 环境下把默认字体设置为 Microsoft YaHei,中文显示效果会比较稳定;如果完全不设置,组件通常沿用 Windows 的系统 UI 字体,字号偏旧。

这里有一个实战中容易踩的误区:不要在运行时反复设置FrameViewer1.Align。如果窗体设计时就已经设置了 Align,运行时再改意义不大,而且可能触发布局刷新。上面这个写法只是为了在完全手写代码的工程里也能跑起来。

4.2 FMX 最小示例:跨平台输出 Hello HTML

FMX 版本的组件在 Delphi 12.3 中安装后,会出现在 FMX 组件页里。假设在 Form 上拖拽后 IDE 生成的控件名是HtmlViewer1,按钮事件可以这样写:

procedure TForm2.Button1Click(Sender: TObject); begin HtmlViewer1.LoadFromString( '<html>' + '<body>' + '<h2>FMX Hello</h2>' + '<p>HTML Component Library v4.6 在 FMX 下同样可用。</p>' + '</body>' + '</html>'); end;

FMX 版不依赖 Windows GDI,因此在 macOS 或 Android 上也能绘制出 HTML 页面。但要注意,移动端的默认字体列表和 PC 完全不同。如果在 Android 上显示中文出现方块,不要急着怀疑 HCL,先检查 Delphi 工程是否启用了自定义字体,或者是否在 FMX 表单的OnCreate里设置了FontManager的字体路径。常见的做法是给 DefFontName 传入平台自带的中文字体名,VCL 用微软雅黑,macOS 用 PingFang SC,Android 用 Droid Sans Fallback 或 sans-serif。

4.3 常用属性、方法和事件速查

初用 HCL 时,掌握几个高频入口就够了。下面的表是基于我实际使用 v4.6 VCL 分支的经验整理出来的,FMX 分支的命名基本一致,但个别属性可能由 IDE 自动生成。

成员类型作用与建议
DefFontName属性设置默认字体,例如 'Microsoft YaHei'
DefFontSize属性默认字号,建议 9 到 12
MarginWidth属性页面左右边距,单位像素
MarginHeight属性页面上下边距
LoadFromString方法从字符串加载 HTML,适合报表模板
LoadFromFile方法从文件加载 HTML,适合离线文档
OnHotSpotClick事件链接被点击时触发,可拦截并自行处理
OnLinkClick事件某些版本中由 OnHotSpotClick 转发,用于外部浏览器

LoadFromFile加载本地 HTML 文件时,路径分隔符建议用绝对路径或相对于ExtractFilePath(Application.ExeName)的路径,避免把相对路径写死在当前目录里。遇到外链时,HCL 默认可能会打开系统默认浏览器;如果希望链接永远不跳转,只需要在事件处理函数里把Handled设为 True。这个机制是后面做自定义协议桥接的基础。

5. 中文乱码、EdgeBrowser 无反应与性能排错

任何 HTML 渲染组件都绕不开字符集问题,HCL v4.6 尤其明显。它不是一个现代浏览器,不会自动嗅探编码,也不会因为你在 HTML 里写了<meta charset="utf-8">就一定不出乱码。乱码的根源通常是 Delphi 字符串和 HTML 字节流之间的编码转换没有做对。

5.1 中文乱码:不只是 HTML 声明问题

我见过很多 Delphi 新人把 UTF-8 的 HTML 文件直接交给LoadFromFile,然后在头部写了 charset,结果中文还是乱码。原因是 Delphi 在读取文件时默认按本地代码页(Windows 中文系统为 GBK)解析字节流,如果文件本身是 UTF-8 无 BOM,premature 转码就会出错。正确做法是先按 UTF-8 解码字节,再交给组件。

uses System.SysUtils, System.NetEncoding; function LoadUtf8Html(const FileName: string): string; var Bytes: TBytes; begin Bytes := TFile.ReadAllBytes(FileName); Result := TEncoding.UTF8.GetString(Bytes); end; // 调用 FrameViewer1.LoadFromString(LoadUtf8Html('report.html'));

逻辑说明:TFile.ReadAllBytes读到的是原始字节,TEncoding.UTF8.GetString明确按 UTF-8 解码成 Unicode 字符串。这个做法比让 HCL 自己读文件可靠,因为不依赖组件的内部编码判断。如果是数据库字段,比如从 SQLite 里读出来的中文备注,也是一样的原理:先拿到字段对应的 AnsiBytes 或 Blob,再统一转成 UTF8 字符串后拼接 HTML。很多人碰到的“Delphi SQLite 乱码”,本质就是 CSV 或 Blob 里存的是 GBK,而拼接进 HTML 后却按 UTF-8 解码。

5.2 别用 EdgeBrowser.Navigate 来做静态报表

有个词在最近的问题里出现频率很高:“Delphi 运行 EdgeBrowser.Navigate 无反应”。这通常是 Edge WebView2 控件在窗口句柄尚未创建、或浏览器进程初始化失败时导致的。如果你只是在做报表打印和邮件模板,完全可以不碰 EdgeBrowser。HCL 自绘引擎没有独立进程,不存在“导航无反应”这种状态,因为它根本不会导航。它只解析你给它的 HTML 字符串。如果给了完整 URL 必须联网,HCL 的能力很弱,这也不是它的设计目标。

反过来,如果确实要用 EdgeBrowser 展示在线页面,排错顺序应该是:先确认 WebView2 Runtime 已安装,然后在FormCreate里调用EdgeBrowser1.CreateBrowser,再在OnNavigationCompleted事件中调用Navigate,不要直接在FormCreate里写一句Navigate('https://...')就完事。HCL 和 EdgeBrowser 的适用场景是互补的,选择依据是页面里到底有没有不可缺失的 JavaScript。

5.3 大表格与图片资源的性能控制

HCL 为每个 HTML 元素保留对象节点,一个大表格如果超过几千行,内存会明显上涨。我能给的最直接建议是:不要把整张数据库表直接铺到 HTML 里。分页、懒加载、HTTP 图片链接可以缓解,但最有效的是拆分页面。比如把每一页报表限制在 500 行以内,连续查看时先Free旧的 FrameViewer,再创建新实例。以下代码适合在反复加载报表时用:

procedure TForm1.ReleaseViewer; begin FrameViewer1.Stop; // 停止当前解析 FrameViewer1.Clear; // 清空页内容 FrameViewer1.Free; FrameViewer1 := nil; end;

StopClear是 v4.6 常见生命周期方法,前者在图片还没下载完时中止解析,后者清空节点树。如果组件是在设计期拖上去的,直接 Free 会在关闭窗体时造成二次释放,所以这里要把FrameViewer1 := nil。比较稳妥的工程做法是运行时动态创建,而不是设计期摆死。

5.4 跨版本编译注意点

虽然 v4.6 支持 D5 到 D11 Alexandria,但你在 Delphi 12.3 里写代码时要小心新语法漏进老版本分支。比如Inline Var、泛型匿名函数只适合新版本。如果有需要交付给 D5 环境的包,建议用$IF CompilerVersion把新语法隔开。另一个常见问题是字符串索引从 1 开始还是 0 开始,这在老版和新版 Delphi 里行为不同,处理 HTML 字符串时尽量用CopyPos这类跨版本统一函数。

6. 用 hcl:// 自定义协议把 HTML 点击事件桥接到 Delphi 后端

安装和基本渲染跑通之后,一个很实用的能力是让 HTML 页面里的链接直接调用 Delphi 方法。最可靠、不依赖 JS 引擎的方式是拦截 OnHotSpotClick 事件,识别hcl://协议头。理解起来像浏览器里的自定义 URI Scheme,只是这里完全由 Delphi 自己处理。

先构造一个 HTML 示例,放在按钮点击事件里加载:

procedure TForm1.ButtonLoadClick(Sender: TObject); begin FrameViewer1.LoadFromString( '<html><body>' + '<h3>自定义协议测试</h3>' + '<a href="hcl://export">导出当前报表</a><br>' + '<a href="hcl://close">关闭窗口</a>' + '</body></html>'); end;

然后在 FrameViewer1 的OnHotSpotClick事件里写:

procedure TForm1.FrameViewer1HotSpotClick(Sender: TObject; const SRC: string; var Handled: Boolean); var Action: string; begin if Pos('hcl://', LowerCase(SRC)) = 1 then begin Handled := True; Action := LowerCase(Copy(SRC, 7, MaxInt)); if Action = 'export' then ExportReport else if Action = 'close' then Close; end; end;

SRC参数是 HTML 中 href 的原始字符串。Handled := True表示这个链接已经被 Delphi 消费,HCL 不会再尝试打开系统浏览器。Copy(SRC, 7, MaxInt)用来去掉hcl://这部分前缀,留下exportclose。这里强制转小写,是为了避免用户在 HTML 里写HCL://EXPORT导致协议判断不一致。

这个模式的进阶价值在于:业务侧同事可以独立写 HTML 文档,只需要按规定好的协议名称拼链接,不需要接触 Delphi 代码。对风险控制也有一个直接好处:白名单机制很简单,只放行exportclose这些固定动作,未识别的协议一律Handled := False,让外部浏览器接管。如果协议参数需要传值,比如hcl://show?id=100,建议再做一层 URL 解码,把&amp;还原成&,再把参数交给专门的数据访问单元。这样前端模板和后端逻辑彻底分离,是 HCL 在小团队里最实用的架构技巧。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询