简介:EhLib VCL 10.2.42 for Delphi 12 Athens 是一套面向 Delphi 开发者的原生 VCL 控件库,覆盖数据库网格、报表、图形图表、日期时间与对话框等常见开发场景,可显著增强桌面应用的数据展示和界面定制能力,广泛适用于进销存、ERP、报表统计等业务系统,也适合需要快速迭代界面的中高级 Delphi 工程师直接集成或二次开发。压缩包共 1490 个文件,约 25.56MB,包含 319 个 PAS 源文件、387 个 DFM 窗体文件、298 个 DCU 编译单元,以及 DPR/DPROJ 项目文件、CHM 帮助文档、位图图标和本地化资源等,既便于安装部署,也方便阅读源码、追溯实现细节,整体目录结构清晰,可快速定位所需组件。已有 352 人学习下载,属于针对 Delphi 12 的较新适配版本。资源中提供 EhDBGrid、EhReport、EhGantt、EhDiagram 等典型控件与可运行示例,可帮助开发者快速掌握分组排序、打印预览、流程绘图等高级用法;同时支持连接 Oracle、MySQL、SQL Server 等多种数据库,配合文档与源码,能有效降低企业级项目中的控件集成和自定义扩展成本。1. 为什么我建议你把 Delphi 12 的控件装上之前先拆开看看Delphi 12 Athens 发布之后,很多从老版本迁过来的项目都卡在同一件事上:控件。你这个“Delphi 控件”的检索词背后,十有八九是已经遇到了 Win32 项目编译过一次、第二次又挂掉的情况。EhLib VCL 10.2.42 for Delphi 12 Athens 这套包,本质上就是一组以网格为中心的 VCL 控件集:TDBGridEh、TDBEditEh、TDBComboBoxEh 这些名字如果你用过 Delphi 7 或者 XE 时代,一定不陌生。它的价值点在于,把数据库表格、下拉框、日期选择、过滤条件、导出 Excel 这些日常 CRUD 功能全部收拢在控件层,业务代码不用自己实现。适合谁?适合正在做管理信息系统、进销存、ERP 客户端、以及那些还在维护老 Delphi 项目但对 Delphi 12 新编译器心里没底的人。别急着双击安装,我们先讲清楚这套包到底是什么、装到哪、怎么确认没装错,再动手。2. 扒开 EhLib VCL 10.2.42:这套控件包里到底有什么,为什么老项目离不了它2.1 不是“一个控件”,而是一套围绕 DBGrid 的组件体系EhLib 从早年流行到现在,核心始终是 TDBGridEh。它和 Delphi 自带的 TDBGrid 最大的区别在于,TDBGridEh 把许多原本要写在 FormCloseQuery、Field.OnGetText、Button 事件里的功能,变成了控件自身的属性。你拖一个 TDBGridEh 到窗体上,连接一个 TDataSet,不需要写一行代码就能得到行筛选、列合计、自动调整列宽、下拉列表、多选、复制粘贴这些行为。这就是老项目离不开它的原因:数据库应用里,网格就是浏览器,业务人员的多数操作都在这个网格上完成。10.2.42 这个版本号说明它不是大版本升级,而是 10.2.x 分支里的一个维护更新。此类版本通常会修复 IDE 注册表里的组件安装路径问题、适配 Delphi 12 的新 RTL、处理 Unicode 字符串在网格单元格里的显示差异,而不是新增控件。你在解压包里看到的大概率是三类文件:运行期包(.bpl/.dcp)、源码(.pas)、示例项目(Demos)。源码目录里的 DBGridEh.pas、DBGridEhEditor.pas 这些是控件本体,Demos 里则是各种业务场景的演示窗体,例如主从表、商品字典联动、行着色。2.2 Delphi 12 Athens 迁移时最容易搞混的三件事第一件事是 Hermes 和旧的 32 位/64 位编译目标。Delphi 12 的默认安装是 Win64 优先,如果你原来项目里引用的是 32 位 BPL,新装的 EhLib 是 64 位版本,那 IDE 里能见到控件,编译项目时却报“无法解析外部符号”。这不是控件坏了,是包的位宽没对上。第二件事是 Unicode 字符串映射。EhLib 老版本里有些属性类型是 AnsiString,Delphi 12 的 String 默认 UTF8,如果你把老版本的事件代码直接粘过来,赋值给 DisplayText 这类属性时会有字符串截断或中文乱码。10.2.42 的改进点多半就在这。第三件事是设计期编辑器。旧版 DBGridEh 的列编辑器是个独立 Form,Delphi 12 的新 IDE 把 Form Designer 改了,如果你装的版本低于 10.x,列编辑器可能弹不出来,只能手动写列定义,非常痛苦。10.2.42 对应的列编辑器是用 VCL 重写的,至少不会出现按两下就崩的情况。2.3 直接看包的目录,判断资源是否完整压缩包解压后,我一般会先看三个目录:Source、Lib、Demos,这三个目录齐全才算是一个可以落地的控件资源。Source 里必须有 DBGridEh.pas、DBCtrlsEh.pas、DBGridEhToolCtrls.pas 这类,Lib 里必须有对应 Delphi 12 Win32/Win64 的 .dcu 文件,Demos 里应有至少一个可以编译的示例工程。如果只有 Win32 的 DCU,没有 Win64 的,那对 64 位项目就是残缺的。拿到 10.2.42 for Delphi 12 Athens 这个包,第一件事不是解压,而是看包名里有没有“Win64”或“All”字样;没有的话,安装后就必须自己编译才能支持 Win64。3. 在 Delphi 12 Athens 里装 EhLib:从解压到 IDE 能认出控件的完整步骤3.1 解压路径与目录设置:不要放进系统盘默认目录第一步,把压缩包解压到一个不带空格、不带中文的路径,比如 D:\Components\EhLib_10_2_42。把控件放在带空格的路径里,比如 “C:\Program Files\EhLib 10.2.42”,在 dcuil 和 bpl 引用阶段很容易出现路径解析错误,IDE 报错信息又不会直接告诉你,是个很隐蔽的坑。解压后,检查 Source 目录下是否有 **.dpk 文件。Delphi 12 需要用项目组文件(.dpk)或运行时包文件(.dpk)来编译。我习惯的做法是先在 Delphi 12 的 IDE 里打开一个空项目,然后选择 File -> Open,定位到 Source 目录中的 EHLIB120.dpk(不同版本后缀数字不同,120 对应 Delphi 12)。双击打开后,会看到 Project Manager 里有一个包含约几十个单元的包。在编译之前,需要把路径加进 IDE 的库搜索路径。打开 Tools -> Options -> Environment Options -> Delphi Options -> Library,在 Library Path 中追加 D:\Components\EhLib_10_2_42\Source; 注意分号与路径。这样做的原因是后续设计期放置 TDBGridEh 到窗体时,IDE 需要编译并加载来源单元,但这一步不做的话,控件只显示为灰色不可用状态。3.2 分清楚运行期包与设计期包:哪个该安装、哪个不该装这是新手最容易弄反的地方。EhLib 里通常有两个包文件,一个是运行期包(Runtime package),通常是 EHLIB120.dpk;另一个是设计期包(Design package),比如 dclEhLib120.dpk。运行期包负责提供控件逻辑,编译进你的 EXE 或作为运行时 BPL 被引用;设计期包负责把控件注册进 Delphi 12 的组件面板,让 IDE 认识这些组件。正确做法是:先打开运行期包,点击 Compile 编译但不安装;再打开设计期包,点击 Install。如果你反了,先装了设计期包,IDE 会报找不到运行期包的错误。很多教程让你两个都点 Install,实际运行期包只编译不安装即可,安装反而会导致运行时和设计时的包冲突。我在现场见过一个典型情况:组件面板里没有 EhLib 页签,原因就是只装了运行期包,没有装设计期包。设计期包的 dcp 后缀里有一个 dcl 前缀,看到这个前缀就应该知道它是设计期包。3.3 编译后如何验证控件是否被正确注册编译并安装完设计期包后,右键 Delphi 12 工具栏,打开 Component Palette,找到名为 EhLib 的页签。正常情况下,页签里会出现 TDBGridEh、TDBNumberEditEh、TDBDateTimeEditEh、TDBLookupComboboxEh 等二十几个控件。如果没看到页签,回到 Project Manager 查看设计期包的编译日志,日志里通常会有一行 “Component TDBGridEh registered” ,有这一行说明注册成功,没看到则说明包没安装成功。验证控件的可用性最直接的方法:新建一个 VCL Application,在窗体上双击 TDBGridEh 组件,它会被放到窗体的左上角。如果能放上去,说明控件已经能正常使用。接着按 F12 切换到窗体文本,找到 object DBGridEh1: TDBGridEh 这行,说明控件已建立了设计时实例,可以进入配置阶段。3.4 编写第一个可运行的测试程序:连接 FireDAC 到一个内存数据集控件装好后,写一段最简单但能证明“控件行为正常”的测试代码。新建一个 VCL 窗体,放一个 TFDConnection、一个 TFDQuery、一个 TDataSource、一个 TDBGridEh、一个 TDBNavigatorEh。注意 TDBNavigatorEh 是 EhLib 自带的数据导航栏,和 VCL 自带的 TDBNavigator 不同。然后在窗体的 OnCreate 事件里写:procedure TForm1.FormCreate(Sender: TObject); begin FDConnection1.DriverName := 'SQLite'; FDConnection1.Params.Database := ':memory:'; FDConnection1.Connected := True; FDQuery1.Connection := FDConnection1; FDQuery1.SQL.Text := 'CREATE TABLE test (id INTEGER, name TEXT)'; FDQuery1.ExecSQL; FDQuery1.SQL.Text := 'INSERT INTO test VALUES (1, ''EhLib'')'; FDQuery1.ExecSQL; FDQuery1.SQL.Text := 'SELECT * FROM test'; FDQuery1.Open; DataSource1.DataSet := FDQuery1; DBGridEh1.DataSource := DataSource1; end;这段代码的重点是验证 DBGridEh 能否直接绑定到 FireDAC 的数据集。不需要额外的连接组件,SQLite 内存库即可。如果运行后网格中显示出一条记录,说明控件、包、路径三者的结合没问题。3.5 常见安装参数说明与调整点上文中涉及的参数有三个关键位:库路径中的 Source 目录、dpk 包文件名、与你项目平台(Win32 / Win64)对应的目标平台设置。.dpk 编译时你在 Project Manager 里右键项目节点,选择 Properties,在 Target Platforms 中勾选你要用的平台。如果只勾了 Win32,项目是 64 位,编译时会报找不到 EhLib 的 DCU;如果两个都勾上,编译时间会长一些,但保证 IDE 和项目都能用。另外,Delphi 12 的 Package Output 目录默认是 $(BDSCOMMONDIR)\Bpl,也就是公共 BPL 目录。如果你在 IDE 里安装时没有写入权限,安装会失败,解决办法是修改包属性中的 Output Directory 指向你自己有读写权限的目录,然后重新编译安装。4. 排错专题:EhLib 在 Delphi 12 下最容易翻车的五个坑,逐个拆解4.1 坑一:控件安装成功,但项目一编译就报“E2209 Required package not found”现象:IDE 的组件面板里能看到 EhLib 页签,控件也能拖到窗体上,但 F9 编译时立刻报 “E2209 Required package not found: dclEhLib120”。原因:设计期包 dclEhLib120 引用了运行期包 EHLIB120,项目工程文件里虽然写了需要 dclEhLib120,但 Delphi 12 的库路径里找不到 EHLIB120 的 .bpl 文件。常见的诱因是把 Source 目录加入了 Library Path,却忘了把编译输出产生的 .bpl 所在目录加进去。解决:在 Tools -> Options -> Library 的 Library Path 里补上输出 .bpl 的目录,通常是包属性中的 Output Directory。我一般直接在包项目里把 Output directory 设置到 $(BDSCOMMONDIR)\Bpl,然后重新编译一次运行期包,确保 .bpl 文件已经在该目录下存在。4.2 坑二:DBGridEh 的列编辑器打不开,右键菜单里没有 Columns 项现象:DBGridEh 拖到窗体上后,双击控件没有任何反应,右键弹出菜单里也只有 Copy、Delete 这类标准的 VCL 命令,没有 “Columns Editor”。原因:这是一个很典型的版本混用问题。如果机器上曾经安装过旧版本的 EhLib,DELPHI 12 的 IDE 在设计期加载的是旧版设计期包,新包被覆盖但没有完全清理注册表。列编辑器属于设计期包的扩展功能,旧包不再提供该功能,而新包的注册信息又被旧包源码路径抢占。解决:先备份自己的代码,然后彻底卸载旧版本,需要清理注册表中 HKEY_CURRENT_USER\Software\Embarcadero\BDS\22.0\Known IDE Packages 里的旧包记录。重新打开 Delphi 12,再安装新版本的设计期包。如果不想动注册表,可以在解压目录里找 Packages 子目录,用其中的 install 脚本重新执行安装,安装脚本通常会把旧包记录覆盖掉。4.3 坑三:Win32 项目编译正常,Win64 项目编译报出找不到 DBGridEh.dcu现象:切换目标平台到 Win64 后重新编译,提示 “F2613 Unit DBGridEh not found” 或者找不到 DCU 文件。原因:这个包本身只包含 Win32 的 DCU,或者你只安装了 Win32 的包。Delphi 12 默认新项目是 Win64,而 EhLib 的 Source 目录里只有 32 位 DCU 时,IDE 编译器无法为 64 位目标生成 .dcu。这是控件包最常见的问题,也和资源包是否完整直接相关。解决:打开运行期包的 .dpk 文件,在 Project Manager 中右键项目,把 Target Platforms 中勾选 Win64,重新编译一次,生成 64 位 DCU 和 BPL,然后再编译项目。如果包本身没有 64 位兼容源码,那只能改用其它兼容版本的控件包。4.4 坑四:中文显示乱码,单元格出现“锟斤拷”或问号现象:网格里从数据库读出的中文内容显示为乱码,部分汉字变成两三个问号或奇怪的间隔符。原因:Delphi 12 默认 String 是 UTF-8,而旧数据库连接组件返回的字节流可能是 GBK 或 ANSI 编码。EhLib 在 TDBGridEh 内部把字段值转为字符串时会按控件里设置的 Unicode 处理方式转换,如果字段未设置正确的字符集,转换就容易出错。另一种常见情况是使用了 Oracle 老驱动的客户端字符集不匹配。解决:在连接参数中显式指定客户端字符集,例如 FireDAC 的 Params 里加 CharacterSet=UTF8;同时给 TDBGridEh 的列设置 Title 字体和单元格字体,通过事件 DataField 的 OnGetText 手动处理编码。一般落地方案是:统一数据库端为 UTF8,不再在控件层做转码。如果无法改数据库,则写一个字段属性事件,在 OnGetText 中把原始字节转换为 UTF-8 字符串。4.5 坑五:放大窗体之后网格没有自适应,空出一大片或列特别挤现象:窗体最大化后,DBGridEh 的列宽没有跟随窗体变化,右侧空白很大,而某些列却变得特别窄。原因:TDBGridEh 支持 OptionsEh 里的 autoWidth 属性和列属性 AutoFitColWidth。但旧版本项目的 DFM 中列对象没有更新的属性记录,从旧 Delphi 迁移到 Delphi 12 后,没有打开设计期的自动调整功能。解决:在设计期选中 DBGridEh,设置属性 AutoFitColWidth := True;或者在代码里写一段统一处理的过程:procedure SetupGridAutoFit(AGrid: TDBGridEh); begin AGrid.OptionsEh := AGrid.OptionsEh + [dghAutoFitColWidths]; AGrid.AutoFitColWidth := True; end;如果你发现上述代码报错,说明 10.2.42 版本里这个属性已经改名或被并入 Constraints,可以打开源码里的 DBGridEh.pas 搜索 AutoFitColWidth,确认当前版本的具体属性名。5. 把这个控件真正用起来:DBGridEh 的列配置、数据联动与导出功能实操5.1 配置列显示、列求和、只读列的三步法拖入一个 TDBGridEh 后,右键选择 Columns Editor,打开列编辑器。点击 “Add All Fields” 可以把当前数据集的全部字段自动生成为列。然后对每一列,在右侧对象面板里设置 Title.Caption 改为中文标题;设置 Footer.Value 为数值字段的合计方式,例如在 Val 列中设置 Footer.ValueType := fvtSum,运行时网格底部会显示合计值。设置 ReadOnly 为 True 可以避免用户直接编辑某些列,但这种只读是控件层行为,不是数据约束。上述方法对应的是设计期配置。运行时动态添加列时,用以下典型代码:var NewCol: TColumnEh; begin NewCol := DBGridEh1.Columns.Add; NewCol.FieldName := 'price'; NewCol.Title.Caption := '单价'; NewCol.Footer.ValueType := fvtSum; end;这段代码的价值点在于:Columns.Add 出的列不会自动和数据集字段绑定,FieldName 必须严格等于数据集字段名,大小写不敏感;Footer.ValueType 会触发 DBGridEh 内部对数据集进行遍历汇总,如果数据集很大,会在打开时卡住,因此需要避免在几十万行的数据集上直接启用列合计。5.2 下拉框联动:LookupComboBox 与主从表显示的配合EhLib 的 TDBLookupComboBoxEh 通常用于解决外键显示问题。比如订单表有一个客户ID,只想在下拉框里看到客户名称,同时把选中的客户ID存入字段。把 TDBLookupComboBoxEh 放到 DBGridEh 的列对应的单元格上,设置 DataField 为 CustID,KeyField 为 ID,ListSource 为客户表的数据源,ListField 为客户名称字段。一个很容易踩的坑是:ListSource 的 DataSet 必须处于打开状态,否则设计期下拉框无法显示数据。我通常在窗体的 OnCreate 里先打开主表,再打开字典表,顺序不能反。如果字典表是静态数据,也可以设置 ListSource.DataSet 为 FDMemTable 并加载数据。运行时动态设置数据源的示例:DBLookupComboboxEh1.DataField := 'CustID'; DBLookupComboboxEh1.KeyField := 'CustID'; DBLookupComboboxEh1.ListSource := dmCustomers.dsCustomer; DBLookupComboboxEh1.ListField := 'CustName';这段代码说明一个事实:Lookup 下拉框本身并不修改主数据集的连接,它只是把下拉框选中的 Key 值塞进当前字段。你的主数据集必须支持编辑状态,否则下拉框点击时会直接报“数据集不可编辑”。5.3 常用数据导入导出:Excel 与 CSV 的处理差异EhLib 自带导出功能,通常是 TDBGridEh 的 SaveToExcel 方法或 TDBGridEhExportToExcel 相关单元。需要用到的代码与配置如下:uses DBGridEhImpExp; procedure TForm1.ExportToExcel(Sender: TObject); var AFileName: string; begin AFileName := GetCurrentDir + '\grid_export.xlsx'; SaveDBGridEhToExportFile(TDBGridEhExportAsTextEh, DBGridEh1, AFileName, False); end;Export 的第一个参数可以换为 TDBGridEhExportAsExcelEh,两种方式的差异在于文本导出会产生逗号分隔文件,Excel 导出会生成 XLS 格式。老版本 EhLib 的 Excel 导出默认生成的是 XLS,不是 XLSX,这是很多人想当然导致打不开的原因。名称中带 OOXML 的单元才输出 XLSX 格式。如果你需要导出带合计行的数据,需要在导出前把 Footer 的合计内容刷新到网格,调用 DBGridEh1.DataGrouping.RefreshFooter 或 DBGridEh1.RefreshFooterValues。不刷新的话,底部合计可能显示为旧数据。5.4 用代码控制行着色,把状态字段变成视觉语义业务系统里最常见的需求之一是按状态给行着色。EhLib 在这点上提供了自定义绘制的钩子,用 OnDrawColumnCell 事件实现。这里给出一段供参考的代码:procedure TForm1.DBGridEh1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumnEh; State: TGridDrawState); begin if FDQuery1.FieldByName('status').AsString = 'Done' then DBGridEh1.Canvas.Brush.Color := clWebLightGreen; DBGridEh1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end;注意:在事件返回前必须调用 DefaultDrawColumnCell,否则单元格里的文字和图标不会绘制出来。Canvas 的字体颜色也可以在这里修改,例如给状态为 “Failed” 的行设置 clRed,同时加粗字体。另外,如果 grid 开了行选择模式,选中行的高亮颜色会被最后的 Canvas.Brush.Color 覆盖,需要在 OnCellClick 里重新绘制选中行。6. 收尾技巧:用 OptionsEh 一次性把老项目的外观拉回现代水平到了这一步,控件已经能跑、能读写、能导出。但如果你的客户打开程序觉得“界面还像 2005 年”,那问题不在于 EhLib 能不能用,而在于老项目里大量默认属性根本没调。我每次接手老 Delphi 项目时,都会强制检查一遍 DBGridEh 的几个关键 OptionsEh 开关。在窗体文本中找到对象 DBGridEh 的 OptionsEh 行,把它展开,重点确认这几个子项:dghAutoFitColWidths 控制列宽自适应,dghRowHighlight 控制鼠标滑过时高亮行,dghVerticalLines 决定网格垂直分隔线是否显示。现代桌面程序的表格不需要太多竖线,关闭后视觉上会更清爽。如果你做的是数据处理后台,希望行高更紧凑,可以把 OptionsEh 里的 dghCellAutoSelect 打开,这样单击单元格时自动全选内容,复制效率会提高很多。我只调整这几个开关的前提是,客户没有额外要求。如果你想要更大胆的外观,比如奇偶行不同底色、列头带排序箭头,就需要额外设置 OddRowColor、EvenRowColor 和 TitleButtons 相关属性,这部分可以在设计期直接给 DBGridEh 的属性树赋值,不需要写代码。做到这一步后,我会把 DBGridEh 的某几个属性保存为一个 Frame 或基类窗体,之后所有新增的业务窗体都继承这个基类,属性统一维护,新窗口自然就带上统一风格。从那以后,我每次在 Delphi 12 里引入新控件包,都会强制走一遍这套流程:先拆包看目录、再编译运行时包、安装设计期包、写一个最小测试程序验证、最后把公共属性固化到基类。这个习惯帮我避开过不少“装完等于没装”的局面,一条一条排查下来,绝大多数报错都能在十分钟之内定位到原因。希望这次 EhLib 的拆解对你也能有一点帮助。本文还有配套的精品资源,点击获取
简介:EhLib VCL 10.2.42 for Delphi 12 Athens 是一套面向 Delphi 开发者的原生 VCL 控件库,覆盖数据库网格、报表、图形图表、日期时间与对话框等常见开发场景,可显著增强桌面应用的数据展示和界面定制能力,广泛适用于进销存、ERP、报表统计等业务系统,也适合需要快速迭代界面的中高级 Delphi 工程师直接集成或二次开发。压缩包共 1490 个文件,约 25.56MB,包含 319 个 PAS 源文件、387 个 DFM 窗体文件、298 个 DCU 编译单元,以及 DPR/DPROJ 项目文件、CHM 帮助文档、位图图标和本地化资源等,既便于安装部署,也方便阅读源码、追溯实现细节,整体目录结构清晰,可快速定位所需组件。已有 352 人学习下载,属于针对 Delphi 12 的较新适配版本。资源中提供 EhDBGrid、EhReport、EhGantt、EhDiagram 等典型控件与可运行示例,可帮助开发者快速掌握分组排序、打印预览、流程绘图等高级用法;同时支持连接 Oracle、MySQL、SQL Server 等多种数据库,配合文档与源码,能有效降低企业级项目中的控件集成和自定义扩展成本。1. 为什么我建议你把 Delphi 12 的控件装上之前先拆开看看Delphi 12 Athens 发布之后,很多从老版本迁过来的项目都卡在同一件事上:控件。你这个“Delphi 控件”的检索词背后,十有八九是已经遇到了 Win32 项目编译过一次、第二次又挂掉的情况。EhLib VCL 10.2.42 for Delphi 12 Athens 这套包,本质上就是一组以网格为中心的 VCL 控件集:TDBGridEh、TDBEditEh、TDBComboBoxEh 这些名字如果你用过 Delphi 7 或者 XE 时代,一定不陌生。它的价值点在于,把数据库表格、下拉框、日期选择、过滤条件、导出 Excel 这些日常 CRUD 功能全部收拢在控件层,业务代码不用自己实现。适合谁?适合正在做管理信息系统、进销存、ERP 客户端、以及那些还在维护老 Delphi 项目但对 Delphi 12 新编译器心里没底的人。别急着双击安装,我们先讲清楚这套包到底是什么、装到哪、怎么确认没装错,再动手。2. 扒开 EhLib VCL 10.2.42:这套控件包里到底有什么,为什么老项目离不了它2.1 不是“一个控件”,而是一套围绕 DBGrid 的组件体系EhLib 从早年流行到现在,核心始终是 TDBGridEh。它和 Delphi 自带的 TDBGrid 最大的区别在于,TDBGridEh 把许多原本要写在 FormCloseQuery、Field.OnGetText、Button 事件里的功能,变成了控件自身的属性。你拖一个 TDBGridEh 到窗体上,连接一个 TDataSet,不需要写一行代码就能得到行筛选、列合计、自动调整列宽、下拉列表、多选、复制粘贴这些行为。这就是老项目离不开它的原因:数据库应用里,网格就是浏览器,业务人员的多数操作都在这个网格上完成。10.2.42 这个版本号说明它不是大版本升级,而是 10.2.x 分支里的一个维护更新。此类版本通常会修复 IDE 注册表里的组件安装路径问题、适配 Delphi 12 的新 RTL、处理 Unicode 字符串在网格单元格里的显示差异,而不是新增控件。你在解压包里看到的大概率是三类文件:运行期包(.bpl/.dcp)、源码(.pas)、示例项目(Demos)。源码目录里的 DBGridEh.pas、DBGridEhEditor.pas 这些是控件本体,Demos 里则是各种业务场景的演示窗体,例如主从表、商品字典联动、行着色。2.2 Delphi 12 Athens 迁移时最容易搞混的三件事第一件事是 Hermes 和旧的 32 位/64 位编译目标。Delphi 12 的默认安装是 Win64 优先,如果你原来项目里引用的是 32 位 BPL,新装的 EhLib 是 64 位版本,那 IDE 里能见到控件,编译项目时却报“无法解析外部符号”。这不是控件坏了,是包的位宽没对上。第二件事是 Unicode 字符串映射。EhLib 老版本里有些属性类型是 AnsiString,Delphi 12 的 String 默认 UTF8,如果你把老版本的事件代码直接粘过来,赋值给 DisplayText 这类属性时会有字符串截断或中文乱码。10.2.42 的改进点多半就在这。第三件事是设计期编辑器。旧版 DBGridEh 的列编辑器是个独立 Form,Delphi 12 的新 IDE 把 Form Designer 改了,如果你装的版本低于 10.x,列编辑器可能弹不出来,只能手动写列定义,非常痛苦。10.2.42 对应的列编辑器是用 VCL 重写的,至少不会出现按两下就崩的情况。2.3 直接看包的目录,判断资源是否完整压缩包解压后,我一般会先看三个目录:Source、Lib、Demos,这三个目录齐全才算是一个可以落地的控件资源。Source 里必须有 DBGridEh.pas、DBCtrlsEh.pas、DBGridEhToolCtrls.pas 这类,Lib 里必须有对应 Delphi 12 Win32/Win64 的 .dcu 文件,Demos 里应有至少一个可以编译的示例工程。如果只有 Win32 的 DCU,没有 Win64 的,那对 64 位项目就是残缺的。拿到 10.2.42 for Delphi 12 Athens 这个包,第一件事不是解压,而是看包名里有没有“Win64”或“All”字样;没有的话,安装后就必须自己编译才能支持 Win64。3. 在 Delphi 12 Athens 里装 EhLib:从解压到 IDE 能认出控件的完整步骤3.1 解压路径与目录设置:不要放进系统盘默认目录第一步,把压缩包解压到一个不带空格、不带中文的路径,比如 D:\Components\EhLib_10_2_42。把控件放在带空格的路径里,比如 “C:\Program Files\EhLib 10.2.42”,在 dcuil 和 bpl 引用阶段很容易出现路径解析错误,IDE 报错信息又不会直接告诉你,是个很隐蔽的坑。解压后,检查 Source 目录下是否有 **.dpk 文件。Delphi 12 需要用项目组文件(.dpk)或运行时包文件(.dpk)来编译。我习惯的做法是先在 Delphi 12 的 IDE 里打开一个空项目,然后选择 File -> Open,定位到 Source 目录中的 EHLIB120.dpk(不同版本后缀数字不同,120 对应 Delphi 12)。双击打开后,会看到 Project Manager 里有一个包含约几十个单元的包。在编译之前,需要把路径加进 IDE 的库搜索路径。打开 Tools -> Options -> Environment Options -> Delphi Options -> Library,在 Library Path 中追加 D:\Components\EhLib_10_2_42\Source; 注意分号与路径。这样做的原因是后续设计期放置 TDBGridEh 到窗体时,IDE 需要编译并加载来源单元,但这一步不做的话,控件只显示为灰色不可用状态。3.2 分清楚运行期包与设计期包:哪个该安装、哪个不该装这是新手最容易弄反的地方。EhLib 里通常有两个包文件,一个是运行期包(Runtime package),通常是 EHLIB120.dpk;另一个是设计期包(Design package),比如 dclEhLib120.dpk。运行期包负责提供控件逻辑,编译进你的 EXE 或作为运行时 BPL 被引用;设计期包负责把控件注册进 Delphi 12 的组件面板,让 IDE 认识这些组件。正确做法是:先打开运行期包,点击 Compile 编译但不安装;再打开设计期包,点击 Install。如果你反了,先装了设计期包,IDE 会报找不到运行期包的错误。很多教程让你两个都点 Install,实际运行期包只编译不安装即可,安装反而会导致运行时和设计时的包冲突。我在现场见过一个典型情况:组件面板里没有 EhLib 页签,原因就是只装了运行期包,没有装设计期包。设计期包的 dcp 后缀里有一个 dcl 前缀,看到这个前缀就应该知道它是设计期包。3.3 编译后如何验证控件是否被正确注册编译并安装完设计期包后,右键 Delphi 12 工具栏,打开 Component Palette,找到名为 EhLib 的页签。正常情况下,页签里会出现 TDBGridEh、TDBNumberEditEh、TDBDateTimeEditEh、TDBLookupComboboxEh 等二十几个控件。如果没看到页签,回到 Project Manager 查看设计期包的编译日志,日志里通常会有一行 “Component TDBGridEh registered” ,有这一行说明注册成功,没看到则说明包没安装成功。验证控件的可用性最直接的方法:新建一个 VCL Application,在窗体上双击 TDBGridEh 组件,它会被放到窗体的左上角。如果能放上去,说明控件已经能正常使用。接着按 F12 切换到窗体文本,找到 object DBGridEh1: TDBGridEh 这行,说明控件已建立了设计时实例,可以进入配置阶段。3.4 编写第一个可运行的测试程序:连接 FireDAC 到一个内存数据集控件装好后,写一段最简单但能证明“控件行为正常”的测试代码。新建一个 VCL 窗体,放一个 TFDConnection、一个 TFDQuery、一个 TDataSource、一个 TDBGridEh、一个 TDBNavigatorEh。注意 TDBNavigatorEh 是 EhLib 自带的数据导航栏,和 VCL 自带的 TDBNavigator 不同。然后在窗体的 OnCreate 事件里写:procedure TForm1.FormCreate(Sender: TObject); begin FDConnection1.DriverName := 'SQLite'; FDConnection1.Params.Database := ':memory:'; FDConnection1.Connected := True; FDQuery1.Connection := FDConnection1; FDQuery1.SQL.Text := 'CREATE TABLE test (id INTEGER, name TEXT)'; FDQuery1.ExecSQL; FDQuery1.SQL.Text := 'INSERT INTO test VALUES (1, ''EhLib'')'; FDQuery1.ExecSQL; FDQuery1.SQL.Text := 'SELECT * FROM test'; FDQuery1.Open; DataSource1.DataSet := FDQuery1; DBGridEh1.DataSource := DataSource1; end;这段代码的重点是验证 DBGridEh 能否直接绑定到 FireDAC 的数据集。不需要额外的连接组件,SQLite 内存库即可。如果运行后网格中显示出一条记录,说明控件、包、路径三者的结合没问题。3.5 常见安装参数说明与调整点上文中涉及的参数有三个关键位:库路径中的 Source 目录、dpk 包文件名、与你项目平台(Win32 / Win64)对应的目标平台设置。.dpk 编译时你在 Project Manager 里右键项目节点,选择 Properties,在 Target Platforms 中勾选你要用的平台。如果只勾了 Win32,项目是 64 位,编译时会报找不到 EhLib 的 DCU;如果两个都勾上,编译时间会长一些,但保证 IDE 和项目都能用。另外,Delphi 12 的 Package Output 目录默认是 $(BDSCOMMONDIR)\Bpl,也就是公共 BPL 目录。如果你在 IDE 里安装时没有写入权限,安装会失败,解决办法是修改包属性中的 Output Directory 指向你自己有读写权限的目录,然后重新编译安装。4. 排错专题:EhLib 在 Delphi 12 下最容易翻车的五个坑,逐个拆解4.1 坑一:控件安装成功,但项目一编译就报“E2209 Required package not found”现象:IDE 的组件面板里能看到 EhLib 页签,控件也能拖到窗体上,但 F9 编译时立刻报 “E2209 Required package not found: dclEhLib120”。原因:设计期包 dclEhLib120 引用了运行期包 EHLIB120,项目工程文件里虽然写了需要 dclEhLib120,但 Delphi 12 的库路径里找不到 EHLIB120 的 .bpl 文件。常见的诱因是把 Source 目录加入了 Library Path,却忘了把编译输出产生的 .bpl 所在目录加进去。解决:在 Tools -> Options -> Library 的 Library Path 里补上输出 .bpl 的目录,通常是包属性中的 Output Directory。我一般直接在包项目里把 Output directory 设置到 $(BDSCOMMONDIR)\Bpl,然后重新编译一次运行期包,确保 .bpl 文件已经在该目录下存在。4.2 坑二:DBGridEh 的列编辑器打不开,右键菜单里没有 Columns 项现象:DBGridEh 拖到窗体上后,双击控件没有任何反应,右键弹出菜单里也只有 Copy、Delete 这类标准的 VCL 命令,没有 “Columns Editor”。原因:这是一个很典型的版本混用问题。如果机器上曾经安装过旧版本的 EhLib,DELPHI 12 的 IDE 在设计期加载的是旧版设计期包,新包被覆盖但没有完全清理注册表。列编辑器属于设计期包的扩展功能,旧包不再提供该功能,而新包的注册信息又被旧包源码路径抢占。解决:先备份自己的代码,然后彻底卸载旧版本,需要清理注册表中 HKEY_CURRENT_USER\Software\Embarcadero\BDS\22.0\Known IDE Packages 里的旧包记录。重新打开 Delphi 12,再安装新版本的设计期包。如果不想动注册表,可以在解压目录里找 Packages 子目录,用其中的 install 脚本重新执行安装,安装脚本通常会把旧包记录覆盖掉。4.3 坑三:Win32 项目编译正常,Win64 项目编译报出找不到 DBGridEh.dcu现象:切换目标平台到 Win64 后重新编译,提示 “F2613 Unit DBGridEh not found” 或者找不到 DCU 文件。原因:这个包本身只包含 Win32 的 DCU,或者你只安装了 Win32 的包。Delphi 12 默认新项目是 Win64,而 EhLib 的 Source 目录里只有 32 位 DCU 时,IDE 编译器无法为 64 位目标生成 .dcu。这是控件包最常见的问题,也和资源包是否完整直接相关。解决:打开运行期包的 .dpk 文件,在 Project Manager 中右键项目,把 Target Platforms 中勾选 Win64,重新编译一次,生成 64 位 DCU 和 BPL,然后再编译项目。如果包本身没有 64 位兼容源码,那只能改用其它兼容版本的控件包。4.4 坑四:中文显示乱码,单元格出现“锟斤拷”或问号现象:网格里从数据库读出的中文内容显示为乱码,部分汉字变成两三个问号或奇怪的间隔符。原因:Delphi 12 默认 String 是 UTF-8,而旧数据库连接组件返回的字节流可能是 GBK 或 ANSI 编码。EhLib 在 TDBGridEh 内部把字段值转为字符串时会按控件里设置的 Unicode 处理方式转换,如果字段未设置正确的字符集,转换就容易出错。另一种常见情况是使用了 Oracle 老驱动的客户端字符集不匹配。解决:在连接参数中显式指定客户端字符集,例如 FireDAC 的 Params 里加 CharacterSet=UTF8;同时给 TDBGridEh 的列设置 Title 字体和单元格字体,通过事件 DataField 的 OnGetText 手动处理编码。一般落地方案是:统一数据库端为 UTF8,不再在控件层做转码。如果无法改数据库,则写一个字段属性事件,在 OnGetText 中把原始字节转换为 UTF-8 字符串。4.5 坑五:放大窗体之后网格没有自适应,空出一大片或列特别挤现象:窗体最大化后,DBGridEh 的列宽没有跟随窗体变化,右侧空白很大,而某些列却变得特别窄。原因:TDBGridEh 支持 OptionsEh 里的 autoWidth 属性和列属性 AutoFitColWidth。但旧版本项目的 DFM 中列对象没有更新的属性记录,从旧 Delphi 迁移到 Delphi 12 后,没有打开设计期的自动调整功能。解决:在设计期选中 DBGridEh,设置属性 AutoFitColWidth := True;或者在代码里写一段统一处理的过程:procedure SetupGridAutoFit(AGrid: TDBGridEh); begin AGrid.OptionsEh := AGrid.OptionsEh + [dghAutoFitColWidths]; AGrid.AutoFitColWidth := True; end;如果你发现上述代码报错,说明 10.2.42 版本里这个属性已经改名或被并入 Constraints,可以打开源码里的 DBGridEh.pas 搜索 AutoFitColWidth,确认当前版本的具体属性名。5. 把这个控件真正用起来:DBGridEh 的列配置、数据联动与导出功能实操5.1 配置列显示、列求和、只读列的三步法拖入一个 TDBGridEh 后,右键选择 Columns Editor,打开列编辑器。点击 “Add All Fields” 可以把当前数据集的全部字段自动生成为列。然后对每一列,在右侧对象面板里设置 Title.Caption 改为中文标题;设置 Footer.Value 为数值字段的合计方式,例如在 Val 列中设置 Footer.ValueType := fvtSum,运行时网格底部会显示合计值。设置 ReadOnly 为 True 可以避免用户直接编辑某些列,但这种只读是控件层行为,不是数据约束。上述方法对应的是设计期配置。运行时动态添加列时,用以下典型代码:var NewCol: TColumnEh; begin NewCol := DBGridEh1.Columns.Add; NewCol.FieldName := 'price'; NewCol.Title.Caption := '单价'; NewCol.Footer.ValueType := fvtSum; end;这段代码的价值点在于:Columns.Add 出的列不会自动和数据集字段绑定,FieldName 必须严格等于数据集字段名,大小写不敏感;Footer.ValueType 会触发 DBGridEh 内部对数据集进行遍历汇总,如果数据集很大,会在打开时卡住,因此需要避免在几十万行的数据集上直接启用列合计。5.2 下拉框联动:LookupComboBox 与主从表显示的配合EhLib 的 TDBLookupComboBoxEh 通常用于解决外键显示问题。比如订单表有一个客户ID,只想在下拉框里看到客户名称,同时把选中的客户ID存入字段。把 TDBLookupComboBoxEh 放到 DBGridEh 的列对应的单元格上,设置 DataField 为 CustID,KeyField 为 ID,ListSource 为客户表的数据源,ListField 为客户名称字段。一个很容易踩的坑是:ListSource 的 DataSet 必须处于打开状态,否则设计期下拉框无法显示数据。我通常在窗体的 OnCreate 里先打开主表,再打开字典表,顺序不能反。如果字典表是静态数据,也可以设置 ListSource.DataSet 为 FDMemTable 并加载数据。运行时动态设置数据源的示例:DBLookupComboboxEh1.DataField := 'CustID'; DBLookupComboboxEh1.KeyField := 'CustID'; DBLookupComboboxEh1.ListSource := dmCustomers.dsCustomer; DBLookupComboboxEh1.ListField := 'CustName';这段代码说明一个事实:Lookup 下拉框本身并不修改主数据集的连接,它只是把下拉框选中的 Key 值塞进当前字段。你的主数据集必须支持编辑状态,否则下拉框点击时会直接报“数据集不可编辑”。5.3 常用数据导入导出:Excel 与 CSV 的处理差异EhLib 自带导出功能,通常是 TDBGridEh 的 SaveToExcel 方法或 TDBGridEhExportToExcel 相关单元。需要用到的代码与配置如下:uses DBGridEhImpExp; procedure TForm1.ExportToExcel(Sender: TObject); var AFileName: string; begin AFileName := GetCurrentDir + '\grid_export.xlsx'; SaveDBGridEhToExportFile(TDBGridEhExportAsTextEh, DBGridEh1, AFileName, False); end;Export 的第一个参数可以换为 TDBGridEhExportAsExcelEh,两种方式的差异在于文本导出会产生逗号分隔文件,Excel 导出会生成 XLS 格式。老版本 EhLib 的 Excel 导出默认生成的是 XLS,不是 XLSX,这是很多人想当然导致打不开的原因。名称中带 OOXML 的单元才输出 XLSX 格式。如果你需要导出带合计行的数据,需要在导出前把 Footer 的合计内容刷新到网格,调用 DBGridEh1.DataGrouping.RefreshFooter 或 DBGridEh1.RefreshFooterValues。不刷新的话,底部合计可能显示为旧数据。5.4 用代码控制行着色,把状态字段变成视觉语义业务系统里最常见的需求之一是按状态给行着色。EhLib 在这点上提供了自定义绘制的钩子,用 OnDrawColumnCell 事件实现。这里给出一段供参考的代码:procedure TForm1.DBGridEh1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumnEh; State: TGridDrawState); begin if FDQuery1.FieldByName('status').AsString = 'Done' then DBGridEh1.Canvas.Brush.Color := clWebLightGreen; DBGridEh1.DefaultDrawColumnCell(Rect, DataCol, Column, State); end;注意:在事件返回前必须调用 DefaultDrawColumnCell,否则单元格里的文字和图标不会绘制出来。Canvas 的字体颜色也可以在这里修改,例如给状态为 “Failed” 的行设置 clRed,同时加粗字体。另外,如果 grid 开了行选择模式,选中行的高亮颜色会被最后的 Canvas.Brush.Color 覆盖,需要在 OnCellClick 里重新绘制选中行。6. 收尾技巧:用 OptionsEh 一次性把老项目的外观拉回现代水平到了这一步,控件已经能跑、能读写、能导出。但如果你的客户打开程序觉得“界面还像 2005 年”,那问题不在于 EhLib 能不能用,而在于老项目里大量默认属性根本没调。我每次接手老 Delphi 项目时,都会强制检查一遍 DBGridEh 的几个关键 OptionsEh 开关。在窗体文本中找到对象 DBGridEh 的 OptionsEh 行,把它展开,重点确认这几个子项:dghAutoFitColWidths 控制列宽自适应,dghRowHighlight 控制鼠标滑过时高亮行,dghVerticalLines 决定网格垂直分隔线是否显示。现代桌面程序的表格不需要太多竖线,关闭后视觉上会更清爽。如果你做的是数据处理后台,希望行高更紧凑,可以把 OptionsEh 里的 dghCellAutoSelect 打开,这样单击单元格时自动全选内容,复制效率会提高很多。我只调整这几个开关的前提是,客户没有额外要求。如果你想要更大胆的外观,比如奇偶行不同底色、列头带排序箭头,就需要额外设置 OddRowColor、EvenRowColor 和 TitleButtons 相关属性,这部分可以在设计期直接给 DBGridEh 的属性树赋值,不需要写代码。做到这一步后,我会把 DBGridEh 的某几个属性保存为一个 Frame 或基类窗体,之后所有新增的业务窗体都继承这个基类,属性统一维护,新窗口自然就带上统一风格。从那以后,我每次在 Delphi 12 里引入新控件包,都会强制走一遍这套流程:先拆包看目录、再编译运行时包、安装设计期包、写一个最小测试程序验证、最后把公共属性固化到基类。这个习惯帮我避开过不少“装完等于没装”的局面,一条一条排查下来,绝大多数报错都能在十分钟之内定位到原因。希望这次 EhLib 的拆解对你也能有一点帮助。本文还有配套的精品资源,点击获取