简介:这份下载是 EhLib v10.2.42 针对 Delphi 5 至 Delphi 12 的完整源码控件包,面向使用 RAD Studio 构建桌面数据库应用的 Delphi 程序员。EhLib 以数据网格、自动筛选、下拉选择与报表打印组件见长,适合需要增强 TDBGrid 交互能力、快速搭建数据管理界面的中高级开发者,也适用于控件自定义编译与多版本兼容调试。压缩包共 1877 个文件,包含 479 个 pas 源文件与 466 个 dfm 窗体文件,覆盖组件核心实现与设计期界面;175 个 dproj 与 160 个 dpk 工程/包管理文件便于按版本分组编译安装;232 个 res 与 137 个 ico 提供编译资源和图标,整体 28.53MB,目录按版本和功能模块组织,检索方便。已有 238 人参与学习下载。读者可获得完整组件源码、帮助文档和示例项目,深入理解数据网格扩展机制,并结合自身 Delphi 版本生成对应运行时/设计期包,有效降低界面控件选型与适配成本。
1. 一句话拆开打包,看看 EhLib.v10.2.42 源码包到底要不要装
“EhLib.v10.2.42 for Delphi 5-12.src.zip”这串名字本身就是一张说明书:它是 EhLib 组件库,版本号 v10.2.42,声明支持从 Delphi 5 到 Delphi 12 这一大片 IDE 版本,而且以 src(源代码)形式发布,不是编译好的 bpl 和 dcu。换句话说,它不会像安装器那样双击下一步就出现在组件面板上,等待你的是我习惯叫“安装三步曲”的流程:解开源码、用目标 IDE 编译对应的包、再把设计时包装回 Delphi。对正在做数据库界面、表格报表,或者还在维护老 Delphi 项目的人来说,这一步绕不开。
这个标题最让人困惑的是“for Delphi 5-12”这个区间。不少新人以为这是万能包,随便在哪个版本里打开就能编译,结果在 Delphi 12 里一开就崩,或者组件面板上什么也没多出来。真实情况是:一套源码要服务整整三代 Delphi 编译器,靠的是条件编译宏和按版本划分的包工程目录,你拿到的是原材料,不是成品。这篇笔记就是帮你把“原材料”变成“组件面板上能拖到窗口里的控件”,顺便把包结构、编译顺序、Library Path 配置和五个高频坑一次讲完。
2. 源码包结构确认与环境准备:先搞清楚 zip 里有什么,再决定装哪个版本
拿到.src.zip后,我建议别急着打开 Delphi,先做五分钟目录侦察。跨版本源码包和普通应用工程最大的不同是:它通常不只有一个工程,而是一组按 IDE 版本组织起来的包工程;找错版本、漏看目录,后面一半时间都会花在排错上。
2.1 解压与侦察:怎么辨认包工程、组件和版本映射文件
常见做法是先把压缩包解压到盘符根目录下的纯英文路径,例如D:\Sources\Delphi\EhLib_V1042。除非你非常清楚自己在干什么,否则别放在桌面、中文目录或系统盘Program Files (x86)下面。Delphi 的编译器对路径里的空格和非 ASCII 字符很敏感,这类问题不会当场爆出来,而是在某个看起来没关联的单元里报错,非常难查。
解压用系统自带的 tar 就行,Windows 10 和 Windows 11 的 tar 可以直接处理 zip 文件:
cd /d D: mkdir D:\Sources\Delphi\EhLib_V1042 tar -xf "D:\Downloads\EhLib.v10.2.42.for.Delphi.5-12.src.zip" -C D:\Sources\Delphi\EhLib_V1042 dir /s /b D:\Sources\Delphi\EhLib_V1042\*.dpk dir /s /b D:\Sources\Delphi\EhLib_V1042\*.dproj dir /s /b D:\Sources\Delphi\EhLib_V1042\*.groupprojtar -xf解开文件并保留压缩包里的目录层级,-C指定目标目录,后面的dir /s /b是递归列出完整路径。这里连搜三次是有原因的:.dpk是 Delphi 2005 之前风格的包工程文件,.dproj是新式 XML 工程文件,.groupproj是工程组文件,把多个包放在一起统一构建。一个成熟的第三方控件包往往三种都有。如果三条命令都没有输出,先在根目录找install.txt、readme.txt或*.inc,这些文件里通常会写明当前版本推荐用哪个 IDE 版本构建。
2.2 版本映射规则:一套源码为什么要分成若干个 Packages 目录
先解释 Delphi 包的两个概念。运行时包提供实际实现代码,编译后是.bpl;设计时包负责把组件注册进 IDE,名字通常带Dcl或Design前缀。普通应用程序只依赖运行时包,而你在 Delphi 组件面板上能看到控件,必须安装设计时包。很多人卡在这:把运行时包 Build 出来了,却找不到可以 Install 的包,其实就是没去工程组里找设计时包。
“for Delphi 5-12”为了实现跨版本,源码包通常会把包工程按 IDE 大版本分目录,像Packages\D5、Packages\D12,或者在文件名里直接标D7、XE2、DX。.dpk是绑定编译器的,老.dpk在新 IDE 里能打开但经常编译不过,.dproj又只有较新的 IDE 能识别。如果 zip 解开后同时有Packages\Delphi12和Packages\Delphi5,永远优先用你当前 IDE 对应的那一版目录,不要拿老目录硬编。.dproj是 XML 格式,可以用文本编辑器看,.dpk是 Delphi 源码格式,两者结构完全不同,这一点在选目录时很有用。
2.3 Delphi 12 的编译器版本与“支持 5-12”这句话的正确理解
Delphi 每个 IDE 版本都对应一个编译器代号,老程序员常说的VER140、VER170、VER260就是编译器在预处理阶段定义的宏。所谓“支持 5-12”,本质上是用这些宏把不同版本的语法差异包在源码里,比如带不带System.、Vcl.、Winapi.前缀。Delphi 12 里打开老文件时报“需要转换”,通常只是工程文件格式升级,源码内容不会变。
为了确认当前版本宏,可以写一小段演示代码,放到一个临时工程里编译:
{$IFDEF VER330} // 这个分支只会在较新编译器下进入 {$ENDIF}不过这个不利于快速判断,我更喜欢直接在源码包里搜索.inc和条件编译段。搜索时可以执行:
dir /s /b D:\Sources\Delphi\EhLib_V1042\*.incinc文件通常是公共宏定义文件,里面可能集中定义了CompilerVersion的判断逻辑。编译报错时,如果错误定位到{$IF}分支,不要急着改源码,先去这个文件里看当前版本宏到底走哪个分支。
3. 用 Delphi 12 编译安装 EhLib 10.2.42:从解压到组件面板的完整操作
假设你已经完成第 2 章的侦察,确认源码包里有可用的.groupproj或.dproj。下面就是在 Delphi 12 里安装这一类源码组件包的标准套路。我把顺序固定为三步:先编译运行时包,再安装设计时包,最后配置 Library Path。跳步或换序,是你接下来一两个小时的定义。
3.1 打开工程组:不要一个个编译单个包
在 Delphi 12 的 IDE 里执行File > Open Project,选中第 2 章找到的.groupproj打开。如果弹窗提示“旧格式项目需要转换”,确认这是包工程而不是普通应用,选择转换并保留副本。打开工程组比打开单个包强的地方在于,工程组管理器会按照依赖顺序列出所有包,你执行一次Build All,IDE 自己会安排编译顺序。手动只编译其中一个包,很容易遇到“依赖的包未编译”的报错。
如果只找到.dproj而没有.groupproj,说明要么这个源码包本身就是单包项目,要么维护者没给你组合工程。我一般会直接打开.dproj,让 Package Manager 解析依赖,而不是自己手工建工程组。命令行方式也可以编译单个包:
set MSB=C:\Program Files\Embarcadero\Rad Studio\12.0\bin\MSBuild.exe "%MSB%" D:\Sources\Delphi\EhLib_V1042\Packages\Delphi12\EhLib.dproj /p:Configuration=Release /p:Platform=Win32 /t:BuildMSBuild是 Delphi 2007 之后标准构建引擎;/p:Platform=Win32是关键,VCL 包绝大多数都只针对 32 位,因为 IDE 本身是 32 位进程,设计时包必须能加载进 32 位 IDE。不要把 Platform 改成Any CPU,Delphi 没有这个值。如果包声明支持 64 位运行时,那是应用项目的事,设计时注册仍按 Win32 处理。命令行适合脚本化,日常打开.groupproj点Build All更直观。
3.2 区分运行时包与设计时包:Install 只能对设计时包做
很多人都翻过这个车:编译工程组全绿,但组件面板上什么都没有。原因不是编译报错,而是没有把设计时包安装进 IDE。看工程组列表时,名字带Run或很短的缩写,是运行时包;名字带Dcl、Design、Reg,是设计时包。在 Package Manager 里右键设计时包,选Install,IDE 完成注册后,组件面板上会出现一个EhLib或类似分类,里面是TDBGridEh、TDBLookupComboboxEh这类控件。
安装之前,我建议先看一眼.dproj里的DCC_OutputDir和DCC_DcuOutput。许多源码包默认把编译产物输出到本地目录,例如Packages\Delphi12\Win32\Release,而 Delphi 的全局Library Path并不包含这个目录。结果就是:包明明编译成功,Install 时提示找不到.bpl,或者应用编译时找不到.dcp,向前排查时总怀疑自己装错了。
3.3 把源码路径和 DCU 输出路径加入 Library Path
在 Delphi 12 中,全局路径配置在Tools > Options > Library > Library Path,用分号分隔多个目录,按从上往下的顺序搜索。还有一个Browsing Path,只负责代码导航,不影响编译。对源码组件包来说,Library Path里至少要加两条:
// Library Path 示例,两行分别对应源码目录和编译输出目录 D:\Sources\Delphi\EhLib_V1042\Source D:\Sources\Delphi\EhLib_V1042\Packages\Delphi12\Win32\Release第一条是源码路径,让你能用 IDE 跳转到第三方组件的实现;第二条是编译产物路径,让 Delphi 启动和编译项目时能正确找到.dcu、.bpl。如果把编译产物放到别的共享目录,则那条目录也要加进来。配置完之后不要急着继续,先把 Delphi 12 完全重启一次再打开工程组,否则 IDE 可能还持有旧的搜索路径缓存。
3.4 验证:组件面板出现新分类,并拖到窗口
完成 Install 后,新建一个 VCL 应用程序,在组件面板上找到新增的 EhLib 分类,把TDBGridEh拖到窗体上。如果这一步正常,说明设计时包已经注册成功。接着把TDBGridEh绑定到一个数据集组件,比如TClientDataSet,运行这个工程。能正常显示界面,说明运行时包、源码路径和应用编译链都通了。若拖到窗体后对象检查器里没有事件,或运行时提示找不到方法,问题多半出在 DCU 版本冲突或 Library Path 顺序,先别急着卸载组件包,往下看第 5 章。
4. Delphi 5 到 12 的兼容性处理:为什么包能跨版本,你却要跟着版本走
比安装更麻烦的是“跨版本”这句话。好多人以为 EhLib 10.2.42 在 Delphi 12 里装好,Delphi 5 的老项目也能直接打开直接编译,这完全想多了。源码包只是让每个 IDE 都能编译一份适配自己的产物,Delphi 12 编译完的.bpl和.dcu,Delphi 5 根本不会认。下面把跨版本要掌握的原理讲透。
4.1 编译器条件宏:源码包用了什么手段让一份代码兼容老编译器
{$IFDEF VERxxx}和{$IF CompilerVersion >= xx}是 Delphi 跨版本最核心的手段。编译器在解析源码时会根据当前 IDE 预先定义好的版本宏,决定哪一段代码进入编译,哪一段被忽略。旧 Delphi 里很多单元名不带System.、Vcl.、Winapi.前缀,新 Delphi 里必须带,否则 IDE 会拼命报错找不到单元。第三方控件源码会把这些差异包在条件编译里,类似这样:
{$IF CompilerVersion >= 30.0} uses System.SysUtils, Vcl.Graphics; {$ELSE} uses SysUtils, Graphics; {$ENDIF}CompilerVersion是编译器提供的浮点数常量,对应不同 IDE 版本。你不需要背下所有版本号,只要知道编译报错时,如果错误定位到{$IF}段,说明当前版本宏没有命中正确分支。不要直接删掉{$IF},应该去源码包里的公共.inc文件里看版本判断逻辑,是不是漏了新版 IDE 的宏值。一次我在模拟项目 X 里遇到Unit not found: System.SysUtils,最后发现就是源码包某个.inc只列到旧版本号,新版编译直接跳过,后面整段都用不了。
4.2 版本识别与“不要用当前 IDE 编译上一代包工程”
Delphi 5 没有泛型,没有默认参数,也没有后来的命名空间机制;Delphi 12 的语法和 RTL 行为已经完全不同。源码包维护者通过条件编译把不兼容的语法隔离,但前提是你选中了正确的包工程目录。我在解压后一定会做的事是:把当前 IDE 对应的包目录记下来,例如Packages\Delphi12,其余老目录归档,绝不参与编译。Delphi 12 打开.groupproj时提示“转换”,一般只是工程文件格式升级;如果提示“未知的包类型”,说明这个包工程只属于更老的 IDE,你应该换更高版本目录。
要快速看一个.dproj使用了哪些版本宏和输出目录,可以执行下面这段 PowerShell:
Get-ChildItem "D:\Sources\Delphi\EhLib_V1042" -Recurse -Filter *.dproj | Select-String -Pattern "DCC_Define|DCP_Output|DCC_DcuOutput" | Format-Table -AutoSizeDCC_Define是工程里声明的自定义编译宏,DCP_Output是.dcp输出目录,DCC_DcuOutput是.dcu输出目录。通过这段输出,你可以快速判断哪些包目录属于哪个 IDE 时代,比逐个打开 IDE 看属性快得多。注意:不要用文本编辑器去改这些 XML 节点,一旦格式损坏 IDE 就没办法打开了。
4.3 升级老 Delphi 项目的包容思路:用源码包建一条“旧项目迁移链”
如果你的目标是把 Delphi 5 或 Delphi 7 的旧项目迁移到 Delphi 12,真正高效的路线不是一次到位。我通常建议按这条链走:先在老 IDE 里保留旧项目可编译,确认旧项目的业务行为;再新建一个过渡 VCL 工程,只放最小的窗体,把 EhLib 控件一个一个加回来;最后再把旧项目整个放进 Delphi 12。这样能把“旧代码”“新 IDE”“新组件包”三个变量拆开,出问题时能定位到底是谁引起的。
过渡工程里可以放一个空窗体和一块TDBGridEh,先不做任何业务逻辑。这个工程一旦能在 Delphi 12 里跑起来,就证明控件包本身没问题,接下来再迁移旧窗体时,报错的根因基本都是旧代码语法,而不是控件装坏了。迁移链路里最容易忽略的是旧项目里引用的其它第三方插件,这些插件如果没跟上版本,会把 EhLib 包的问题和它们混在一起,排查时特别浪费时间。
4.4 源码包与安装版的选型:什么场景必须用源码包
同类控件通常有安装程序和源码包两种发布形式。安装程序会自动把.bpl和.dcu放到 IDE 默认目录,看起来省事,但团队协作时问题很多:每个人 IDE 版本小版本号不同,二进制包可能不兼容;升级控件时要重新点安装器;想追踪控件源码、打断点看实现,根本做不到。源码包的优势在于版本可控、可重新编译、可跨 IDE 分发,劣势是每个开发者都要会编译和配置,入门成本高。下表是我的选型参考:
| 对比点 | 安装版/二进制版 | src.zip 源码包 |
|---|---|---|
| 安装速度 | 快,双击完成 | 慢,需自己编译 |
| 跨 IDE 小版本 | 依赖维护者动态 | 自己重编即可 |
| 调试进源码 | 困难 | 方便 |
| 团队统一 | 容易漂移 | 能锁版本 |
| 适合人群 | 快速上手、个人环境 | 团队项目、老项目迁移 |
如果你是一个人写个人小工具,安装版当然够用;如果是给公司项目搭底座,我会坚持用源码包并记录编译步骤。下面的第 5 章内容也是基于这段和老项目一起走过的踩坑经验写下来的。
5. EhLib 10.2.42 安装避坑:这 5 个坑我踩过不止一回
安装跨版本源码组件包的报错很有特征,很多问题都不是控件本身错了,而是环境顺序和路径冲突。这里写五条我反复遇到过的问题,每条都保持“现象 → 原因 → 解决”的记录方式,方便你直接对照排查。
5.1 组件面板一片空白,Install 按钮却是灰的
现象:Build All 已经成功,但在 Package Manager 里右键某个包时,Install选项是灰的,组件面板也没有新增分类。
原因:选中的是运行时包,不是设计时包。Install 动作只对设计时包开放,运行时包没有注册 IDE 组件的能力。还有一种情况是当前打开的工程本身是个普通应用程序,不是包工程,IDE 不会让你点 Install。
解决:回到工程组里找名字带Dcl或Design的包,右键选择 Install。如果工程组里根本没有带Dcl的包,说明这份源码包可能只提供了运行时库,或设计时包在别的目录下,继续搜索*Dcl*.dproj。
5.2 编译时提示 F2581 Cannot open file "EhLib.inc"
现象:新建一个 VCL 工程,编译使用控件的单元,IDE 报F2581 Cannot open file 'EhLib.inc'。
原因:.inc文件是公共宏文件,源码里用{$INCLUDE引用了它,但 include 搜索路径默认只覆盖源码文件所在目录,不覆盖 IDE 全局搜索路径。如果你解压时把目录结构拆散,或手动把某个.pas复制到其它目录,就会找不到同级的.inc。
解决:在源码目录里搜索*.inc,把所在的那一层目录加入 Library Path 的最前面;如果嫌全局配置太重,也可以用绝对路径写{$INCLUDE 'D:\Sources\Delphi\EhLib_V1042\Source\EhLib.inc'}。但注意,绝对路径会让源码包失去可移植性,我一般只在应急时用。
5.3 从其他版本复制过来的 dcu/dcp 导致 IDE 启动崩溃
现象:安装完成后的第一周一切正常,某天打开 Delphi 12 时启动缓慢甚至 Access Violation。
原因:常见于有人把Library Path指到共享的旧组件目录,或把旧版本的.bpl、.dcu复制到了当前输出目录。DCU 是编译器版本强绑定的中间文件,Delphi 12 加载了 Delphi 7 编译出的 DCU,内存布局不一致,IDE 在扫描包时就会崩。
解决:删掉 Library Path 里所有指向旧缓存目录的路径,清掉项目里的__history、__dcu目录后重新 Build:
rd /s /q D:\Sources\Delphi\EhLib_V1042\Packages\Delphi12\Win32\Release再重新编译,确保当前 IDE 只加载本次编译出来的产物。
5.4 中文路径或有空格路径导致编译报错
现象:包安装在D:\我的库\Delphi 组件\EhLib\下,编译时一会找不到.bpl,一会链接资源失败,报错位置每次都不同。
原因:.dproj和 IDE 内部生成的.identcache文件对路径里的空格、中文处理得不一致,再加上源码包里有些脚本可能是旧式路径拼接,遇到非 ASCII 字符直接断掉。这个问题不是控件专属,是很多老 Delphi 组件通病。
解决:把整个组件目录移到纯英文而且不带空格的路径,这是最彻底的做法。如果团队项目必须用中文路径,就把 EhLib 的包目录和项目输出目录分开,输出目录保持纯英文,并且不把源码放在项目目录下。
5.5 编译报错“Unit ... was compiled with a different version of ...”
现象:单独编译一个单元能过,整个项目编译却报两个组件单元版本不匹配,错误信息经常指向某个.dcu文件。
原因:源码包目录里混入了旧版本编译出的.dcu或.dcp,IDE 搜索源码的同时找到了旧目标文件,目标文件里的版本校验信息与当前编译不一致,于是中断。
解决:执行一次彻底清理再重建。在工程组管理器里右键选 Clean,或者直接删掉输出目录里的.dcu、.bpl、.dcp:
del /s /q D:\Sources\Delphi\EhLib_V1042\Packages\Delphi12\Win32\Release\*.dcu del /s /q D:\Sources\Delphi\EhLib_V1042\Packages\Delphi12\Win32\Release\*.bpl清理后重新 Build All。同时把 Library Path 里的顺序改为 Source 在前、输出目录在后,让 IDE 优先命中源码,避免再次捡到旧产物。
6. 进阶:验证安装、路径配置和 Debug 技巧
安装成功不等于环境稳定。我自己的习惯是维护一个“最小验证工程”,专门用来在被安装的第三方控件异常时快速判断责任方。这个工程只有两个窗体设置:一个空窗体,一块TDBGridEh,数据源绑定一个TClientDataSet,不需要写任何业务逻辑。运行时能做到下面三件事,就说明控件安装链路是通的:一是组件面板里能找到 Ehlib 分类;二是把TDBGridEh拖到窗口上,对象检查器能正常列出字段和事件;三是运行后窗口能展示出数据表的行列,绑定字段并滚动不崩。
调试时真正有用的技巧是让 IDE 报错时直接定位到源码,而不是弹一个“找不到断点”的对话框。安装时把Source目录放进Library Path后,我在 Delphi 12 里给TDBGridEh的某个方法设断点,F9 后能停在第三方控件实现的源码行,而不是只停留在调用方。这就验证了两件事:它加载的是源码包,不是二进制包;当前包和 IDE 搜索顺序匹配。断点能进源码,遇到问题就不会把控件当黑匣子处理。
最后再说一个长期维护的教训:每次装完一个版本,都要把解压路径、Library Path、编译顺序、输出的.bpl位置记进项目里的build.md。这个习惯最初是我在维护模拟项目 X 时养成的,当时换了电脑,同一个源码包重新装却怎么都编不过,最后发现缺了一条全局路径没写进文档。源码包本身没有玄学,路径和版本记录做得足够清楚,十年前的组件照样能在 Delphi 12 里跑。希望这份笔记能帮你避开我走过的弯路,一次就把 EhLib 10.2.42 装干净。
本文还有配套的精品资源,点击获取