ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

Delphi5开发人员指南光盘:官方示例与WinHelp转CHM的长期化利用

Delphi5开发人员指南光盘:官方示例与WinHelp转CHM的长期化利用

简介:《Delphi5开发人员指南光盘》是一套面向Delphi5初学者和中级开发者的学习资料,围绕Borland Delphi5这一经典的快速应用程序开发环境,系统讲解Object Pascal语言、VCL组件库、RAD拖放式开发、ADO/BDE数据库访问及内置调试器等核心内容,同时也涉及IDE自定义、第三方组件扩展、数据库驱动配置等实操技巧,适合希望补全Windows桌面应用开发技能的读者。压缩包共收录1414个文件,以pas源代码、dfm窗体定义、res资源文件、dpr工程文件为主,配合大量cfg/dof工程配置、bmp图标、dpk/dcp包文件以及少量avi演示视频,整体约2.96MB,轻巧且便于离线查阅;文件覆盖Pascal单元、窗体布局、工程结构、资源脚本等多种类型,可满足代码学习、界面复刻和项目打包等不同需求。已有234人学习浏览该资源,内附示例工程、公共单元、数据库相关组件和多媒体素材,并涵盖从界面搭建、属性设置到数据库连接、调试排错的具体场景,可作为日常练习与二次开发的重要参考。

1. Delphi5开发人员指南光盘:一张常被当成废塑料的官方知识库

Delphi5开发人员指南光盘,是当年随《Delphi 5 开发人员指南》成套发售的官方资料盘。老工程师手里一旦有它,改历史项目时第一反应是翻这张盘,而不是上网乱搜——因为盘里的示例工程和帮助文档跟 Delphi 5 的 RTL/VCL 版本严格对齐,网上流传的代码片段大多来自更高版本,拿到 D5 里一编译就报错。对还在维护存量 Delphi 5 业务的团队来说,这张盘是少数“版本完全对得上”的权威参照。

很多人拿到盘只把带目录的说明文档拷走,示例源码和帮助体系原封不动,等于把最值钱的部分浪费了。这张盘实际装了四样东西:完整的 WinHelp 帮助、按书章节组织的示例工程、一套可挂进 IDE 的开发文档,以及若干附加组件和工具。它不是一个电子书光碟,而是一个可以离线搭建的参考环境。文档挂进 IDE、示例跑通之后,它的可用性会远超你预想。

这张盘对两种人最有价值:一种是守着 Delphi 5 维护业务系统、想让官方示例帮自己快速定位 API 用法的开发者;另一种是手里刚好有老盘、想系统上手 Delphi 5 的初学者。下面按“盘里有什么 → 怎么接进 IDE → 示例怎么跑通 → 老盘有哪些坑 → 怎么升级成长期资产”的顺序讲清楚,每步都按常见做法落到底。

2. 光盘内容拆解:文档、示例、组件三类资源分别在哪、怎么用

这张盘不是什么高深的东西,但它的目录结构决定了你后面所有操作顺不顺手。不同批次的光盘目录名会有差异,我按功能习惯把它分成三块:帮助文档、示例工程、附加组件与工具。先按块认清,再决定哪些进硬盘、哪些先不装。顺序反了容易犯两种错:一是把 .hlp 单独拷出来,丢了目录树;二是把组件包全装上,结果把 IDE 搞出一堆版本冲突。

2.1 帮助文档区:WinHelp 体系的文件关联与第一次打开行为

光盘里的帮助是 WinHelp 格式,不是后来的 .chm。一个完整的 WinHelp 文档从来不止一个 .hlp 文件:左侧目录树来自同名 .cnt 文件,搜索索引依赖 .fts 和 .gid 文件,而且这两个索引文件是第一次点“搜索”页签时现生成的。如果你只复制 .hlp、不复制 .cnt,打开帮助只剩内容页没有目录树;如果是直接在光盘上点开,索引文件想写写不进,搜索功能会一直转圈。

正确打开方式是把整块帮助目录先复制到硬盘,双击 .cnt 看目录树,双击 .hlp 看具体主题页。第一次使用搜索时,WinHelp 会花几十秒到几分钟建全文索引,这个时间跟文件数量和光驱速度强相关。我一般先复制到硬盘再打开,一是避免老光驱反复读盘,二是让 .fts/.gid 有地方落盘,下次秒开。

还有一个容易踩的细节:.hlp、.cnt、.gid、.fts 这四个后缀必须待在同一个目录里,缺一个就退化成“能打开但没法检索”。所以复制的时候别自作聪明只挑 .hlp,整目录拷贝是最省事的做法,具体命令在第 3 章。

2.2 示例源码区:范例工程的组织方式与相对路径依赖

示例区是这张盘里最值得反复看的资源。目录按书本章节组织,每个目录放一组完整工程,包含 .dpr 工程文件、.pas 单元、.dfm 窗体,以及若干 .res 资源。多个例子会共享一套公共单元,这些公共单元通常放在一个共用目录里,工程文件通过相对路径或库路径引用它们。所以千万别把某个 .pas 单独拖出来用到自己项目里,一旦脱离原目录结构,它在工程里引用的资源文件马上找不到。

这类示例的价值在于“跟书严格对应”。书里讲某控件的一段用法,配套例子就是那段话的可运行版本。我维护老项目时经常这样用:把要解决的问题翻译成控件名和属性名,去示例目录里搜同名目录,直接打开它的 .dpr,看它怎么组合属性、怎么处理事件、怎么在运行时改状态。比自己对着帮助文件猜写法快得多。

复制示例区时,要保留整个目录层级,包括看起来空着的子目录。某些工程的 .res 或图标文件放在深层子目录里,缺了它,编译报错会非常隐蔽,只提示“无法打开文件”,不告诉你缺的是谁。

2.3 附加组件与工具区:先评估再安装,别全盘照收

光盘上通常还带了第三方组件包和工具安装程序,这部分最容易让人翻车。组件包是给示例工程用的增强控件,也有部分是独立工具。下面是三类资源的常规判断方法:

资源块常见内容使用建议
文档区WinHelp 帮助、配套说明整目录复制到硬盘,挂进 IDE
示例区按章节组织的 .dpr/.pas/.dfm完整保留目录结构,保持只读
附加组件/工具第三方控件包、辅助工具安装包只装示例依赖项,其余按需评估

判断“要不要装”的标准很简单:先打开你想跑的示例工程编译一次,报“找不到类”或“找不到单元”再去安装对应的组件包;不报错就不用装。学习阶段最忌一把梭全装上,第三方包的某些单元名可能和官方单元重名,装完反而把 IDE 的单元解析顺序搞乱。生产维护阶段更要注意,组件包的授权方式和版本兼容性要先看清楚,别为了一个示例装一堆将来要卸的工具。

3. 把光盘接进 Delphi 5 IDE:复制、挂帮助、配库路径三步走

这一章是把“光盘”变成“开发环境参考源”的核心操作。三步做完,你在 IDE 里按 F1 能查到盘上帮助,打开示例工程能直接编译,公共单元能被 IDE 自动找到。整个过程用到的命令和菜单都是 Delphi 5 时代最常见的做法,后面所有章节的演示都依赖这套环境。

3.1 整盘复制到硬盘:robocopy 参数与老化光驱的配合

复制整张盘,Windows 下我一般用 robocopy。它比资源管理器拖拽稳,原因有两条:一是对读取失败的文件有明确的重试控制,不会无声无息地跳过;二是退出码可判断结果,便于确认复制是否完整。下面是常用命令:

:: 把光驱 D: 的内容复制到 C:\DevRef\Delphi5 :: /E 连空目录一起拷,/R:1 /W:1 限制重试次数,防止老盘卡死 :: /COPY:DAT 保留数据、属性和时间戳,/NFL /NDL 不逐文件刷屏 robocopy D:\ C:\DevRef\Delphi5 /E /R:1 /W:1 /COPY:DAT /NFL /NDL

参数逻辑要说明一下:/E 是必须的,示例目录里的空子目录可能就放着项目要引用的资源占位;/R:1 /W:1 把重试压到一次,老光盘有划伤区域时,robocopy 默认无限重试会卡很久;/COPY:DAT 保留时间戳,Delphi 5 的 IDE 根据源文件和 DCU 的时间戳判断要不要重编译,时间戳乱了会出现“编译了但不生效”的假象。

robocopy 有两个容易误判的点:一是退出码,1 表示“有文件被复制”,7 以内都是成功,只有大于等于 8 才是真失败;二是复制到一半报错时,别反复重试同一张物理盘,先检查盘面。如果某文件始终读不出来,直接跳到第 5.3 节做整盘镜像,镜像成功后再从镜像里补拷。

注意:复制完成后,建议给整个目录加上只读属性。示例工程本来就该保持原始状态,只读可以防止 IDE 把 .dcu 等生成物直接写进源码目录,也能避免误改官方示例。

3.2 把帮助文件挂进 IDE:Help 菜单的自定义入口

光复制还不够,得让 IDE 的 F1 帮助能跳到这份文档。Delphi 5 的帮助管理入口在菜单 Help > Customize,打开 Help Options 对话框,里面注册当前 IDE 能调用的所有帮助文件。操作步骤:

  1. 启动 Delphi 5,打开 Help > Customize。
  2. 在对话框里选择“添加”或“浏览”,选中刚才复制到硬盘的 .hlp 文件。
  3. 确认同名 .cnt 也在同目录,IDE 会用它生成目录树。
  4. 调整注册列表顺序,把盘上这份开发指南放在默认帮助之后或之前,看你的使用习惯。

为什么不能直接在光驱上打开然后指望 IDE 记住:WinHelp 在打开时会在同目录写 .gid/.fts 索引文件,光盘是只读介质写不进去。这也是“必须先复制到硬盘”的底层原因。挂载完成后,随便打开一个工程,光标停在某个关键字上按 F1,如果弹出来的主题来自这份指南,就说明注册成功。

这里有个常见误用:有人图省事,直接把 .cnt 拖进 IE 或现代浏览器,想看帮助内容。.cnt 不是网页,浏览器只会显示一段纯文本大纲,点不动。正确入口永远是 WinHelp 编辑器或注册进 IDE 后按 F1。

3.3 库路径设置:Library Path 与 Search Path 的分工

示例工程的公共单元要能被 IDE 找到,得理解 Delphi 5 里两条路径的分工。Library Path 在 Tools > Environment Options > Library 里设置,是全局的,IDE 把这条路径自动拼进所有工程的单元搜索范围,适合放“始终要用”的公共目录。Search Path 在 Project > Options > Directories/Conditionals 里设置,是工程级的,只对当前工程生效。

我一般这样配:把示例区里那个放公共单元的目录加入全局 Library Path,保证所有示例工程打开就能解析;把偶尔会用到的第三方组件源码目录加进具体工程的 Search Path,避免全局路径里塞太多东西导致单元重名。顺序也有讲究,IDE 按路径先后顺序解析同名单元,排在前面的优先。所以官方目录要放在第三方目录之前,防止某个同名单元把官方实现顶掉。

配置完成后验证方法是:新建一个空工程,在 uses 里写一个示例公共单元的单元名,按 Ctrl+Shift+F11 打开工程选项,看 Search Path 栏,再尝试编译。如果 IDE 能解析到这个单元,说明库路径生效;如果还报“Can't find unit”,检查路径拼写和目录名大小写,老工具对路径格式比较敏感,结尾别省略反斜杠,也别用含空格的路径。

4. 示例工程从打开到跑通:两个必改选项与编译排错

示例工程是照着“书本阅读体验”打包的,不是照着“调试友好”打包的。直接双击 .dpr 就按 F9,大概率会走进两个坑:一是没有调试信息,断点打不上;二是生成的 .dcu 直接写进源码目录,污染只读的参考资料。本章讲两个必改选项,再给一套编译报错的分类排查法。

4.1 两个必改工程选项:Debug 信息与输出目录

打开任意一个示例工程后,先动两个地方,别急着编译。第一个是 Project > Options > Compiler:把 Optimization 从默认的“Maximum”切到“None”,勾上 Debug information。不关优化,单步执行时行号对不上,watch 窗口里局部变量显示“变量被优化掉”,等于白调试。勾上调试信息,DCU 里才带符号表,这是后续跟读代码的前提。

第二个是 Project > Options > Directories/Conditionals:Output directory 填一个固定目录,比如 .\Build,或者直接用系统临时目录。留空时,IDE 把 .dcu 写在源码同目录,也就是光盘复制出来的只读目录里。如果你按第 3.1 节加了只读属性,这里会直接报“Cannot create file”;就算没加只读,生成物和源码混在一起,过两天就分不清哪些是原始的、哪些是编译出来的。

两个选项改完再按 Ctrl+F9 编译。编译通过后,我习惯先在 Output 目录里看一眼 .dcu 是否按预期生成,确认输出目录设置真的生效,再继续后面的调试。这一步花一分钟,可以避免后面把生成物误当成源码拷走。

4.2 编译报错分类:DCU 版本、控件缺失、路径找不到

示例工程的编译报错看似五花八门,按特征可以收敛成三类,对应三种处理方式:

报错特征常见原因对应处理
Unit … was compiled with a different version of …残留 DCU 与当前编译器选项不一致Project > Build All 强制全量重编译
Class T… not foundDFM 引用了未安装的控件Component > Install Packages 或安装盘上组件包
Can't find unit …Search Path 没覆盖共享单元目录把目录加进工程 Search Path

第一类的处理核心是“Build All”。Delphi 5 的普通 Compile 按时间戳判断,可能沿用旧 DCU;Build All 无视时间戳全量重编。老示例经过多次复制和路径调整后,DCU 时间戳经常比源文件新,这时候普通编译不会重编,报错信息就特别像“玄学”。

第二类要先定位是哪个单元缺控件。把报错展开,找到“Class Txxx not found”里的 Txxx,去工程 uses 里查它是哪个单元声明的,再查这个单元是不是盘上组件包提供的。是的话就去 Component > Install Packages 里看包有没有装上,或者直接在组件菜单里安装盘上的 .dpk 包。

第三类最现实,就是第 3.3 节说的 Search Path 配置问题。复制示例时如果改了目录层级,尤其是把公共单元目录挪了位置,必然触发这类报错。解决的第一件事不是改代码,是把工程根目录和目标目录的上下级关系重新对一遍。路径问题不解决,改代码都是白费。

4.3 跑通后怎么跟读:单步、监视与书本对照

编译通过只是开始,真正有价值的是跟读官方示例。我习惯这样操作:先找到示例里跟书上章节对应的那个事件处理过程,在过程第一行按 F5 下断点,然后 F9 运行触发它。在断点处按 F8 单步跳过,遇到自己关注的调用就按 F7 进入,这样能看清官方示例在运行时到底调了哪些属性组合。

监视变量用 Ctrl+F5 弹出 Add Watch,把对象属性直接写进 watch,比如某个数据集组件的 State 或 RecordCount,运行时就盯着它变。View > Debug Windows > Watches 可以打开监视窗口批量管理。这一套和看普通代码完全不一样,它能让你看到“书上没写、但运行时才发生”的细节,比如属性赋值顺序对状态的影响。

另外提醒一句,一部分数据库相关示例依赖老式数据库引擎 BDE 和别名配置,这在现代系统上很折腾。跟读到这类示例时,如果发现它卡在数据库连接上,别急着怀疑代码,先看 BDE 配置和别名。实在跑不起来的数据库实例,把关注点放在它的数据访问组件用法上,这部分代码逻辑仍然能读、能抄。

5. 老光盘避坑清单:WinHelp 失效、中文乱码、盘片老化

老光盘的坑,十个里有八个不在代码本身,而在“载体”。文件读不出来、帮助打不开、文字显示乱码,这些坑不解决,源码再权威也用不上。这章按“现象 → 原因 → 解决”的顺序写四条最常见的踩坑记录,都是实际操作中一定会遇到的。

5.1 WinHelp 在 64 位系统上打不开

现象:双击复制出来的 .hlp,系统提示“需要安装 Windows 帮助程序”,或者干脆没反应;在 64 位系统上尤其明显,32 位系统通常还能开。

原因:WinHelp 依赖 32 位帮助主机组件,而 64 位系统默认不再内置它。老光盘的帮助全是 .hlp 格式,所以版本越新的系统越容易打不开。

解决:安装 32 位帮助主机组件,也就是常说的 winhelp32 补丁,从系统更新渠道或可信软件站下载对应版本,装完 .hlp 就能打开。如果不想在干净环境里多装一个旧组件,也可以先用带 32 位环境的虚拟机打开看内容,或者直接跳到第 6 章,把 .hlp 转成 .chm,一劳永逸。

5.2 中文注释乱码:GBK 原文件与现代编辑器的冲突

现象:把示例里的 .pas 或 .dfm 用现代编辑器打开,中文注释和字符串全都变成乱码;但在 Delphi 5 IDE 里打开却正常。

原因:Delphi 5 时代的源码文件是 GBK/ANSI 编码,现代编辑器默认按 UTF-8 读取,编码不一致就显示乱码。

解决:给老文件做批量转码,只用于检索和阅读,不要回写。命令行处理最快:

# 把示例目录里所有 .pas/.dfm 从 GBK 转成 UTF-8,输出到同名 .utf8 文件 # 转换结果仅供现代工具检索,不要拿回 Delphi 5 里编译 find ./DemoSrc -type f \( -name "*.pas" -o -name "*.dfm" \) | while read f; do iconv -f GBK -t UTF-8 "$f" > "$f.utf8" done

这里有个关键边界:转码文件只能给阅读理解用,千万别把 UTF-8 文件存回原名再拿到 Delphi 5 里编译。Delphi 5 的 IDE 按系统 ANSI 代码页解析源码,UTF-8 的中文字节会被拆成乱码字符甚至直接报“Invalid character”。所以正确姿势是原始 GBK 文件留在原目录给 IDE 用,转出来的 .utf8 副本单独放一个索引目录。另外 .dfm 虽然是窗体描述文件,本质还是文本,同样受编码影响,转码时要带上。

5.3 光盘读取失败:先镜像、再使用,别和物理盘较劲

现象:读取时光驱咔咔响,复制文件到一半报 I/O 错误;有的目录能看见但文件打开失败;同一张盘换台机器结果还不一样。

原因:CD 反射层老化、盘面划伤、光驱激光功率下降,三者叠加。物理盘的状态只会越来越差,每多读一次就多一次损伤。

解决:第一原则是别再用物理盘反复试,尽快做整盘镜像。镜像是一次性的扇区级读取,之后所有文件操作都对着镜像做,物理盘从此收起来。Linux 或 macOS 下用 ddrescue 最合适:

# /dev/sr0 是光驱设备,先做整盘镜像,再做文件操作 sudo ddrescue /dev/sr0 /srv/Delphi5_DevGuide.iso /srv/delphi5_rescue.log # 镜像完成后挂载 ISO,再从中复制文件 sudo mount -o loop -t iso9660 /srv/Delphi5_DevGuide.iso /mnt/d5

ddrescue 的特点是边读边记录日志,坏扇区跳过,之后可以断点续读,日志文件就是进度记录。它做的是扇区级复制,所以光盘的 Joliet 长文件名、目录结构、时间戳都能完整保留,比在资源管理器里拖着复制可靠得多。Windows 下用常见的镜像工具也能达到同样效果,关键是一致的:选“生成镜像文件”而不是“直接复制文件”,这样才保留完整结构。镜像做完,把 ISO 挂进虚拟光驱,剩下的操作和读一张新盘没有区别。

提示:镜像成功的那一刻,建议把 ISO 再备份一份到另一个物理介质。老光盘的价值就在这份镜像里,镜像丢了,盘也就真的没了。

5.4 组件和 DCU 版本错配:先分清三类报错再动手

现象:示例工程拿到手编译,报组件类找不到或单元版本不一致;有人第一时间去网上找新版本组件,越换越乱。

原因:盘上的组件包是 Delphi 5 时代编译的,DCU 和包文件都绑定当时的 RTL 版本。把工程拿到更高版本 IDE 里编译,或者给 D5 装了版本对不上的第三方包,都会出现这类错配。

解决:先分清报错属于哪一类,再决定动作。如果只是“DCU 版本不一致”,按第 4.2 节 Build All 或删掉旧的 DCU 目录就能解决。如果是“类找不到”,先确认这个控件是不是示例依赖的盘上组件,是就去安装对应的原版组件包,别拿新版替代——新版控件的属性、事件签名很可能和老示例不兼容。如果工程本身要在更高版本 IDE 里跑,那就做好心理准备:示例工程作为“读代码”的资料仍然有效,但“直接编译通过”不保证,组件包需要重新安装或替换。我的习惯是:学用法用 D5 原版跑通,谈迁移才去碰新版本。

6. 把老资源升级成长期参考库:HLP 转 CHM 与源码全文索引

老光盘最有价值的资产是它的内容,载体反而最不重要。最后一章给出两个把资源长期化的做法:一个解决“帮助在新系统打不开”,一个解决“示例太多找不到”,做完之后这张盘就从“偶尔翻一翻的旧物”变成“随时可检索的工具库”。

6.1 HLP 转 CHM:反编译、转码、打包的三步链

把 .hlp 转成 .chm,等于让帮助文档在新系统上获得新生。常见做法分三步:先用一个能在当前系统跑通的 HLP 反编译小工具,把 .hlp 里的每个主题导出成 HTML 文件;再做一轮编码转换,把导出的 HTML 从 GBK 转到 UTF-8;最后用经典的 HTML Help Workshop 打开自动生成的 .hhp 工程,一键 Compile 出 .chm。

# 反编译导出后的主题目录 topics/ 统一转码,再交给 CHM 编译工具打包 find topics/ -type f -name "*.htm" | while read f; do iconv -f GBK -t UTF-8 "$f" > "$f.tmp" && mv "$f.tmp" "$f" done

转码这一步一定不能省。反编译工具导出的 HTML 保留原编码,直接打包成 CHM 后,在新系统上打开中文主题会乱。转完码后,在 HTML Help Workshop 里确认 .hhp 工程文件引用的文件路径没有中文空格问题,然后编译。出的 .chm 可以直接双击打开,也可以再挂回 IDE 的帮助列表,替换掉那个已经打不开的 .hlp。

6.2 给示例源码建一个可全文检索的索引文件

帮助文档转完了,示例源码也要解决“找得到”的问题。我的做法是把整个示例区合并成一个 UTF-8 文本索引,任何现代编辑器都能对它做全文搜索。脚本很短:

# 把示例源码合并成单个 UTF-8 文本索引,方便全文检索 # 只读不改原文件,索引是快照,不参与后续编译 from pathlib import Path root = Path(r"C:\DevRef\Delphi5\DemoSrc") out = Path("delphi5_demo_index.txt") exts = {".pas", ".dfm", ".dpr", ".inc"} with out.open("w", encoding="utf-8") as f: for p in sorted(root.rglob("*")): if p.suffix.lower() in exts: f.write(f"\n===== {p} =====\n") f.write(p.read_text(encoding="gbk", errors="replace"))

脚本里两个参数值得说:encoding="gbk" 是按老文件的实际编码读取,errors="replace" 是防止某个文件里混入异常字节导致整个任务中断。跑完后,用编辑器打开这个索引文件,搜控件名、属性名、API 名,几秒钟就能定位到官方示例里的真实用法,比在几十个目录里逐个翻快得多。

我早期接过一个遗留项目,靠网上博客补 Delphi 5 的知识,三天没跑通一个表格控件示例;后来把这张盘按上面的流程重建完,当天就定位到官方示例里的一组属性组合,问题当场解决。那张盘其实早就在手边,只是我一直没把它当工程资产看待。老技术不可怕,可怕的是资料还躺在光盘里没用起来。这套流程做完,剩下的就是把它变成你的日常检索习惯,希望帮到你。

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

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进