☰
Delphi 12.3下TRichView 22.1控件安装、集成与避坑指南
2026/10/8 11:16:11 网站建设 项目流程

简介:面向 Delphi 12.3 开发者的 TRichView 22.1 控件资源包,专为需要富文本编辑、文档显示与打印能力的桌面应用而准备。TRichView 是 Delphi 生态中常用的第三方富文本控件库,该包适用于中高级 Delphi 程序员在项目中集成高级文本处理功能,如复杂排版、表格、图片混排等。资源包内共收录 2000 个文件,压缩后大小约 99.62MB,文件构成以 cpp 源文件(1555 个)和 h 头文件(357 个)为主,可直接用于查看控件实现细节和编译链接;同时附有 xml 配置文件、txt 文本说明、2 个 pdf 参考文档以及 1 个 htm 帮助页,方便使用者快速了解控件接口、运行配置与技术文档。内含多个功能单元示例,覆盖 Unicode 处理与主窗体交互等典型场景,可帮助开发者快速搭建测试工程,缩短集成调试周期。当前已有 81 人浏览学习,整体适合需要深度定制富文本交互的 Delphi 项目团队作为基础组件与参考蓝本。

1. TRichView 22.1:Delphi 12.3 下最顺手的富文本组件包

说真的,在 Delphi 12.3 里做富文本编辑,你绕不开 TRichView。系统自带的 RichEdit 一旦遇到多段落样式、图片混排、PDF 导出这些需求,翻车概率相当高;自己从零写编辑器根本不现实。TRichView 22.1 把只读展示、可编辑、打印输出拆成了 TRichView、TRichViewEdit、TRichViewPrint 三个对象,一套安装包全给齐,不用再找第三方配套。适合做 OA 审批流里的正文编辑框、公告管理后台的正文录入、合同模板套打这一类场景。下面就是我解包、安装、跑通并导出 PDF 的完整记录,参数和坑都列在这里。

2. 安装准备:解包、路径配置与第一个运行程序

2.1 解包后的目录结构:Source、Packages、Demos 都管什么

拿到Delphii 12.3控件之TRichView-22.1.rar以后,第一步当然是解包。这里有一条血泪经验:解压路径别用带空格或中文的目录,比如C:\Users\张三\My TRichView,这类路径在旧版 IDE 上编译时容易报File Not Found,看起来玄学,实际上就是路径解析在空格处中断了。我统一解到D:\Libs\TRichView22,后文所有配置都按这个路径来。

解包后的目录大致长这样:

目录内容你该关心什么
Source核心单元源文件RichView.pas、RVFuncs.pas、RVStyle.pas 等运行期核心
Packages各版本 Delphi 的工程文件找 Delphi12 或 Delphi12Win64 对应的 dproj/bdsproj
Demos官方示例工程RVEdit、RVPrint 是最好上手参考
Docs帮助文档与发行说明主要看版本兼容性说明

有个容易犯的误会:以为安装控件就是把 .pas 文件直接拷进自己的项目目录。不是这样。TRichView 是一组控件的集合,正确做法是用 Packages 里的工程文件编译出设计期包(.bpl),让 IDE 加载组件注册逻辑,运行时再由项目的 dcu 链接进入你的程序。Source 目录里的单元只负责运行逻辑,Packages 目录才负责把控件注册到 IDE。

另外注意,Delphi 12.3 默认同时支持 Win32 和 Win64 目标。如果你两个平台都要发布,Packages 目录下通常会有对应的子目录,比如Delphi12和Delphi12Win64,两者最好都编译一遍,否则切换目标平台时会遇到Unit not found。

2.2 配置 Delphi 12.3 的 Library Path:这一步省了后面必翻车

TRichView 22.1 的安装包不会自动帮你修改 IDE 设置。如果你直接新建项目,在窗体上拖 TRichViewEdit,大概率会看到F2613 Unit 'RichView' not found之类的报错。这不是组件没装上,而是 IDE 的 Library Path 里没有 Source 目录,编译器找不到 dcu。

我一般这么配置:

  1. 打开Tools → Options → Environment → Library → Library Path。
  2. 点右上角的文件夹图标,添加两条路径:
    • D:\Libs\TRichView22\Source
    • D:\Libs\TRichView22\Packages\Delphi12
  3. 点 OK 保存。如果你同时做 32 位和 64 位开发,还要把Delphi12Win64目录也加进 Library Path。

提示:Library Path 是全局生效的,会应用到所有打开的 Delphi 实例和后续新建的项目。如果某个老项目只想局部使用,也可以把路径加在 Project → Options → Delphi Compiler → Search Path 里。不过我建议直接加全局,省心。

配置完路径以后,编译一个小测试项目,确认uses里能自动找到RichView、RVStyle这些单元。如果 Build 消息窗里出现dcu not found,回到 Library Path 检查路径拼写,特别是版本目录名,不同发行版可能叫Delphi12,也可能叫DXE12,以你手上的包实际目录名为准。

2.3 编译并安装设计期包:让控件出现在组件面板

Library Path 解决的是运行期单元搜索,设计期组件注册还得靠安装包。

打开Packages\Delphi12目录下的主工程文件,一般是richview.dproj或RichViewEdit.dproj。在项目管理器里右键工程名,先Build,编译通过后再右键Install。这时 Delphi 会把它生成的设计期 .bpl 加载进 IDE,并弹出确认框告诉你组件已注册。

需要留意的一点:同一个包可能有多个变体,比如richview_runtime.dproj和richview_design.dproj。如果你打开的是运行时包,Install 按钮是灰的。必须找到带设计期注册的那个工程,通常文件名带design,或者在包内工程列表里能看到哪些是 runtime 哪些是 design。装完设计期包后,到Component → Install Packages里确认列表中有这个 .bpl,没有的话点 Add 手动把编译出来的 .bpl 文件加进去。

组件面板上应当出现TRichView、TRichViewEdit、TRichViewPrint、TRVStyle等新图标。如果连编译都没过,优先检查 2.2 的路径配置,其次检查当前 Delphi 版本和包文件版本是否匹配。我从 RAR 里解出来的这个版本写着 22.1,对应 Delphi 12.3 是没问题的,但你要是拿这套包去喂 Delphi 10.4,那就得做好 API 对不上的心理准备。

2.4 验证安装:写一段代码确认 TRichViewEdit 可用

光看到图标还不够,得跑起来才算数。新建一个 VCL 工程,在窗体上拖入TRichViewEdit,命名为rveMain,再放一个Button。在窗体的OnCreate里写这段验证代码:

procedure TForm1.FormCreate(Sender: TObject); begin // 第一段:以默认样式插入文本,0 表示新建段落 rveMain.AddText('我是 TRichView 22.1 跑起来的第一段富文本。', 0); // 后续内容:-1 表示追加到当前段落,不另起新段 rveMain.AddText('这一段紧接上面,用 -1 就是追加。', -1); // 再插入一段:0 强制换段 rveMain.AddText('这里另起一段,可以看到文档结构里段落数增加了。', 0); end;

说明:AddText是 TRichViewEdit 在文档尾部插入文本的快捷方法。第一个参数是文本内容,第二个参数是段落索引取值:0 或正整数表示以新段落插入,-1 表示向当前段尾追加。运行后如果窗体上出现三段文字,说明运行期链接没问题。再加一个按钮写文件:

procedure TForm1.btnSaveClick(Sender: TObject); begin // 保存前重排一次,确保内部样式数据同步 rveMain.Format(True, False); // 存成 RTF 文件 rveMain.SaveRTF('test.rtf'); end;

Format(True, False)的第一个参数是允许重排,第二个参数是是否强制刷新显示。保存 RTF 的动作会遍历当前文档所有段落,把字体、颜色、对齐方式写入文件。如果这段流程全部走通,安装阶段就结束了。

3. TRichView 的核心对象与文档模型:先搞懂再动手

3.1 TRichView、TRichViewEdit、TRichViewPrint 的分工与选型

第一次用 TRichView 的人很容易被组件面板上那一排长得差不多的控件搞晕:TRichView、TRichViewEdit、TRichViewPrint,到底该拖哪个?我的判断标准很简单,一句话:要给人编辑就用 Edit,给人看就用只读版,要出纸或出 PDF 再加一条打印分支。

对象定位典型场景是否允许用户输入
TRichView只读富文本展示公告详情、合同预览否
TRichViewEdit可编辑富文本编辑器主窗体是
TRichViewPrint打印与导出打印到实体打印机、PDF只读

TRichViewEdit 自带完整的键盘输入、鼠标选择、右键菜单逻辑,如果你只是拿来展示,会出现无意义的光标闪烁,反而增加维护成本。反过来,如果用户确实要改内容,你却用了只读的 TRichView,就得自己实现输入事件和光标逻辑,等于重新造一个编辑器。实务上我见过不少人在这两者之间反复横跳,最后都改回了正确选型。

TRichViewPrint 跟前两个不一样,它不承载文档本身,而是通过属性引用一个 TRichView 或 TRichViewEdit 的文档,然后在打印设备上重新排版输出。有个常见误解是打印必须单独维护一份文档,其实不用,示例代码里直接把rvPrint.RichView := rveMain指过去就能打,文档始终只有一份。

3.2 段落与内联:TRichView 的存储模型

TRichView 的文档模型是分层的:顶层是 Document,其下是段落(Paragraph),每个段落拆成若干行,行内是内联元素。内联元素可以是文本片段、图片、表格、水平线等。这个模型本身不复杂,真正要留意的是它把“段落样式”和“字符样式”完全分离了,这个设计在 TRVStyle 对象里体现得最明显。

TRVStyle 维护两个列表:TextStyles 是字符样式,ParaStyles 是段落样式。往文档里插内容时,不是每段都写一遍字体参数,而是引用这两个列表的索引。样式复用的好处就在这里:你改了样式表里一条,文档里所有引用它的段落会一起变。看个例子:

// 在窗体上放一个 TRVStyle 对象,配置两条样式 RVStyle1.TextStyles.Add.FontName := '微软雅黑'; RVStyle1.TextStyles.Add.Size := 12; RVStyle1.ParaStyles.Add.Alignment := rvaCenter;

第一行在字符样式表里加了一条“微软雅黑”字体,默认字号沿用控件的 DefFontSize;第三行在段落样式表里加了一条居中对齐。Add方法返回的是新增样式的索引,索引从 1 开始,因为 0 是默认样式。之后写段落的时候,传样式索引进去就行:

// 第一个参数是要写的文本,第二个参数是段落样式索引 // 1 表示使用前面新增的居中段落样式 rveMain.AddText('这段文字会居中显示。', 1);

这种按索引引用的设计有一个连锁效应:如果你删除了样式表里的某条样式,但文档里还有段落引用它,输出时就会出现样式退化成默认,表现为“字体突然变回默认黑体”“对齐方式不对”。所以管理样式表时不要乱改项的顺序,尤其是老项目升级过程中,样式索引一变,历史存档的显示就会出问题。

3.3 文件格式支持矩阵:RTF、RVF、HTML 的读写边界

TRichView 把文件格式的支持做成了多组属性,最容易混的是 RVF 和 RTF。RVF 是 TRichView 自家的二进制格式,读写速度和保真度都高,适合程序内部做自动存档;RTF 是给外部交换用的,样式映射会有取舍。

格式读写边界与坑点
RVF支持支持内部使用首选,数据完整
RTF支持支持老版本 Word 生成的文件,嵌套表格可能错位
HTML支持支持读外部站点 HTML,字体兼容性差,图片路径要小心
DOCX不直接支持不直接支持需要通过 Word 或第三方库转成 RTF 再进入

推荐的做法是:程序内部存档走 RVF,用户交互文件用 RTF,DOCX 一律先转再进。RTF 路径在 5.3 节里我会把踩过的字体坑写细,这里先记一句话:能转就转,别拿二进制 DOCX 硬塞给 TRichView。你非要支持 DOCX,可以走一条老路:调用 Word 的 COM 接口先把 DOCX 另存为 RTF,再交给 TRichView 读入,稳定但依赖 Office 环境。

4. 实战集成:把 TRichView 嵌进业务系统

4.1 搭建一个可用的编辑工具栏:字体、对齐、列表

编辑器的价值在于操作顺手。你不需要把 Word 的所有功能搬进来,但字体、字号、加粗、对齐、列表、撤销重做这六个功能是最基本的。每个按钮背后的逻辑都很短,关键在于理解“修改当前选择区的样式”这个统一入口。

// 加粗按钮:切换当前选择区的粗体标志 procedure TForm1.btnBoldClick(Sender: TObject); begin // Style 指向当前光标位置的样式对象 rveMain.Style.Bold := not rveMain.Style.Bold; end; // 字体下拉框:直接改当前选择区的字体名 procedure TForm1.cboFontChange(Sender: TObject); begin rveMain.Style.FontName := cboFont.Text; end; // 字号下拉框:改字体大小 procedure TForm1.cboSizeChange(Sender: TObject); begin rveMain.Style.Size := StrToIntDef(cboSize.Text, 12); end;

这三段代码处理的是同一个东西:TRichViewEdit 的Style属性。当你选中一段文字时,Style返回的是这一段的样式对象,赋值操作会立刻作用到选区。不操作选区时,改的是命令行后续输入会采用的样式,跟 Word 的输入习惯一致。理解这一点之后,再加粗、倾斜、下划线、字体颜色,全部是一个套路,不需要额外记 API。

对齐和列表改的是段落属性,不是字符属性,动作稍微绕一点点:

// 居中对齐:把当前段落的样式索引切换到已定义的居中样式 procedure TForm1.btnCenterClick(Sender: TObject); begin // CaretPos.Y 是光标所在的行号,通过它拿到段落对象再改样式索引 rveMain.Paragraphs[rveMain.CaretPos.Y].StyleNo := 1; // 1 对应 RVStyle 里定义的居中样式 end;

这里的StyleNo是段落样式的索引,也就是 3.2 节里ParaStyles.Add返回的那个序号。如果你只有默认样式 0 和居中样式 1,上面的代码就能在两种状态间切换。列表按钮的复杂程度取决于你的需求,简单项目我直接操作样式索引,复杂项目才去用列表专用的接口。工具栏整体布局建议用 TToolBar 加 TActionList,把每个按钮的 OnClick 集中管理,后续加功能不会把 Form 单元写成屎山。

4.2 保存与加载:文件读写和流式读写的两种姿势

文件读写适合做“打开/另存为”功能,界面代码很直接:

// 打开 RTF 文件 procedure TForm1.btnOpenClick(Sender: TObject); begin if dlgOpen.Execute then begin // 先清空当前文档,避免旧内容残留 rveMain.Clear; // 加载后自动重排 rveMain.LoadRTF(dlgOpen.FileName); end; end; // 另存为 RTF procedure TForm1.btnSaveAsClick(Sender: TObject); begin if dlgSave.Execute then begin rveMain.Format(True, False); rveMain.SaveRTF(dlgSave.FileName); end; end;

Clear是必须的。TRichViewEdit 的文档是累积式的,不先清空,加载新文件时旧内容还留在文档里,结果就是新旧两段混在一起。很多新手在这儿的翻车姿势是:连续打开两个文件,第二个文件的内容跟在第一个后面。

流式读写对应的是数据库存储场景。把文档内容直接存进 BLOB 字段,下次从 BLOB 读出来恢复:

// 保存到内存流,再把流交给数据库 BLOB 字段 procedure TForm1.SaveToBlob(blob: TStream); var ms: TMemoryStream; begin ms := TMemoryStream.Create; try // 写入流,这里用的是 RTF 流接口 rveMain.SaveRTFToStream(ms); ms.Position := 0; // 把整个流复制到 BLOB blob.CopyFrom(ms, ms.Size); finally ms.Free; end; end;

SaveRTFToStream和SaveRTF本质是同一套写入逻辑,多出来的是“不一定落盘”这一点。如果你系统已经有通用附件表,把这段字节序列存进去就行。读回时对应LoadRTFFromStream,同样记得先Clear。

4.3 导出 PDF:直接打印与 ReportBuilder 两条路

PDF 导出是业务系统最常见的下游需求。TRichView 本身不带 PDF 引擎,但常见做法都是往“打印”方向靠,这条路最省事。第一条路是直接让用户选一个 PDF 虚拟打印机,比如 Windows 自带的 “Microsoft Print to PDF”,然后用 TRichViewPrint 走打印流程:

// 用系统 PDF 虚拟打印机导出 procedure TForm1.btnPrintPDFClick(Sender: TObject); begin // 指定输出设备,名称就是系统中已安装的打印机队列 rvPrint.AssignPrinter('Microsoft Print to PDF'); // 把当前编辑器内容挂给打印对象 rvPrint.RichView := rveMain; // 打印从第 1 段到最后一页 rvPrint.Print(1, rveMain.Document.Paragraphs.Count); end;

AssignPrinter的参数是打印机名,Windows 11 上默认带 “Microsoft Print to PDF”,Windows Server 版可能要自己装这个虚拟打印机。Print的两个参数是起始段落和结束段落索引,这里传了 1 到总段落数,就是全文打印。打印弹出的对话框会让你选择输出路径,这一步是系统行为,TRichView 管不了。

第二条路是集成 ReportBuilder。TRichView 官方示例里有跟 ReportBuilder 配合的 demo,核心思路是把富文本内容放进TppRichView控件,再交给 ReportBuilder 的 PDF 引擎导出。这种方式适合报表头、正文、签章都在同一张 PDF 里的场景。配置项多一些,但可控性最强,导出的 PDF 自带书签、权限设置这些企业级功能。遇到复杂报表,我会直接用 ReportBuilder 这条路,把 TRichViewPrint 当作纯粹的打样工具用。

5. 避坑指南:编译报错、乱码、内存问题的排查记录

5.1 msxmldom.dcu not found

现象:编译项目时,IDE 消息窗报F2613 Unit 'msxmldom' not found,而且报错出现在 TRichView 的单元文件里,自己的代码还没轮到编译。

原因:TRichView 的功能单元里有少部分对 XML 的依赖,当你的 uses 列表引用了这些单元,编译器就去找msxmldom.dcu。默认情况下,Delphi 12.3 的库路径没把 XML 相关 DCU 所在目录加全,于是报错。

解决:在Tools → Options → Library → Library Path里补上$(BDSLIB)\$(PLATFORM)\release,或者更直接地,在项目 uses 里显式加xmldom。如果你根本用不到 TRichView 的 XML 功能,就别把触发它的单元挂到 uses 列表里,问题自然消失。从热搜词的词频来看,这个报错在不少 Delphi 环境里都撞到过,算是 IDE 环境类问题,不是控件本身的缺陷。

5.2 读入 RTF 中文乱码

现象:加载旧系统的 RTF 文件,界面里中文显示成问号或方块,英文正常。

原因:大部分老 RTF 文件头部写的是\ansi,编辑器按默认代码页解析,中文编码没对上。Delphi 12.3 本身是 Unicode 环境,TRichView 读入 RTF 时却按文件头声明的代码页解析,如果 RTF 头部没有\ansicpg936,中文就乱了。

解决:在加载前设置 RTF 读取选项:

// 指定 RTF 读取时使用 GBK 简体中文代码页 rveMain.RTFReadProperties.CodePage := 936; // 之后再加载 rveMain.LoadRTF('old_doc.rtf');

RTFReadProperties是一个属性对象,CodePage设成 936 会让读入引擎按简体中文解码。这个属性同样影响剪贴板操作,如果你在程序里粘贴别处的中文出现乱码,优先检查这一项。正规的做法是读 RTF 文件头里有没有\ansicpg936,没有就手动指定,有就只读不设。

5.3 保存的 RTF 在 Office 里样式丢失

现象:程序导出的 .rtf 文件,在 Word 里打开,部分段落字体变成默认体,对齐也丢了。

原因:写入 RTF 时,TRichView 要把字体名、字号按 RTF 的字体表序列化。如果文档里用的字体没有同步到 RTF 字体缓存,写出的字体字符映射就成了默认值。多数时候是你在代码里动态改了Style.FontName,但没有触发内部字体表刷新。

解决:保存前强制重排一次:

// 强制重排,让内部字体表跟当前样式同步 rveMain.Format(True, False); // 再保存 rveMain.SaveRTF('output.rtf');

Format的第二个参数如果传 False,只更新内部布局结构,不影响显示;传 True 则连屏幕一起重绘。保存前刷一次,字体表就跟着同步了。另外如果你用了“微软雅黑”这类字体但目标机器没装,Word 打开后照样退化成默认字体,这是系统层面的事,TRichView 管不到。

5.4 程序退出时的内存报错

现象:关闭主窗体时程序闪退,错误信息是Invalid pointer operation,或者调试器停在释放某对象的行上。

原因:最常见的原因是动态创建的 TRVStyle 或字体对象没有释放,而 TRichViewEdit 在销毁文档时仍引用着它。窗体容器销毁子控件是按创建顺序的反向来的,如果你在 FormCreate 里手动 Create 了样式对象,它的销毁时机比窗体自身晚,就出现了二次释放或悬空引用。

解决:遵循一个原则——能放在窗体上的组件就用设计期放置,别动态创建。如果必须动态创建,注意释放顺序:

procedure TForm1.FormDestroy(Sender: TObject); begin // 先清空文档,释放内部迭代器 rveMain.Clear; // 再释放动态创建的样式对象(如果有) FStyle.Free; end;

注意Clear与Free的先后顺序:先释放文档再释放样式。反过来会出现文档里还有段落引用一个已释放的样式对象,访问时直接非法指针异常。这个坑在退出时报错的表现最隐蔽,因为平时编辑都正常,只在关闭程序那一刻崩。

5.5 组件没出现在面板上

现象:Install 操作成功,但组件面板找不到 TRichView 系列控件。

原因:你装的可能是个运行时包,不是设计期包。只有设计期包会执行RegisterComponents注册过程,运行时包只包含逻辑代码。另一个原因是你同时装了 32 位和 64 位两个版本的包,IDE 加载了其中一个,另一个把面板上的同名控件覆盖掉了。

解决:到Component → Install Packages里检查 bpl 名称,带design的才是设计期包。如果装了两个版本的同名控件,全部卸载,只保留当前项目对应位数的那一个,然后重启 IDE 再看面板。重启这个动作听着笨,但 Delphi 面板缓存偶尔就是要重启才刷新,属于老传统了。

6. 进阶技巧:用 TRichViewPrint 导出 PDF 的参数调优

前面的 PDF 导出只是“能出文件”,但业务上你大概率还喘不过气:页面尺寸不对、边距不统一、中文偶尔发虚。真正调参的地方在 TRichViewPrint 的 PageSetup 对象上,它控制所有打印输出的布局参数。单位是千分之一英寸,很多人在这里栽过,举例 A4 纸宽 210 毫米,换算过来就是 8270,高 11690。

// 设置 A4 页面与统一边距 rvPrint.PageSetup.PageWidth := 8270; rvPrint.PageSetup.PageHeight := 11690; rvPrint.PageSetup.LeftMargin := 1000; rvPrint.PageSetup.RightMargin := 1000; rvPrint.PageSetup.TopMargin := 1000; rvPrint.PageSetup.BottomMargin := 1000;

这几个 Margin 值每个都是 1000,约合 25.4 毫米,正好是一英寸。边距值如果设成 0,某些打印机驱动会拒绝输出,因为物理打印区域不允许无边距,文档看着没问题,一打印就提示越界,白费一张纸。

另一个常见需求是页眉页脚。TRichViewPrint 支持给每个页面附加页眉和页脚,输出页码和文档标题。我一般是在页脚区域放一个格式化的日期和页码,既省事又显得专业。

至于中文渲染发虚的问题,多数是 PDF 虚拟打印机默认分辨率不够。Windows 自带的 “Microsoft Print to PDF” 固定输出 300 DPI,够用了。如果你用自定义虚拟打印机,检查它的输出 DPI 别设在 150 以下,低于这个值小字号中文必糊。字体方面,导出 PDF 时优先选系统中已安装的字体,TrueType 字体在打印渲染管线里都比 GDI 旧字体稳定。

我的习惯是把这些配置封装成一个方法ExportToPDF(const OutFile: string),内部固定好页面参数、边距和打印机选择,项目里所有需要导出 PDF 的按钮统一调它。这样可以避免在十几个窗体里复制粘贴同一套设置代码,改一处等于改全部。另外,导出前我会强制Format(True, False)一次——从那次遇到样式丢失的问题之后,我给自己定的规矩就是:凡是涉及输出,不分是 PDF 还是 RTF,一律先重排再写,没例外。这个习惯救了我好几次,希望帮到你。

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

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

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

立即咨询