☰
EhLib 11.0.21在Delphi 12中的安装配置与DBGridEh实战指南
2026/10/12 5:03:25 网站建设 项目流程

简介:EhLib 11.0.21 - D12 是一套面向 Delphi 12 开发者的商业级 VCL 控件库,用于增强桌面应用的数据展示、表格编辑与打印导出能力。它尤其适合需要快速构建数据密集型管理系统的中高级 Delphi 工程师,能在可视化交互与后端数据绑定之间提供成熟方案。压缩包共 2000 个文件,以 dfm 表单资源、pas 源码、res 资源文件为主,配齐 dproj/dpk 工程与包定义、ico 图标及 chm 帮助文档,整体大小约 67.79MB,可直接安装到 Delphi 12 组件面板并参照示例工程上手。目前已有一千四百余人学习下载。资源内包含完整源码、示例项目、图标素材以及图文说明文档,可支撑从控件注册、窗体布局到事件处理的完整开发闭环;其中的 demo 工程覆盖网格、树、图表等典型场景,能帮助开发者快速掌握排序、过滤、分组、打印等常用功能,并在实际项目中二次复用。

1. 先搞清楚 EhLib 11.0.21 在 Delphi 12 里到底能省多少事

做 Delphi 开发的人,尤其是一直维护老项目的,应该都有过这种经历:项目从 Delphi 7 一路迁到 Delphi 10.4,再到 Delphi 11、12,编译越来越顺,结果一打开窗体发现一堆第三方控件找不到类,最要命的就是网格控件。delphi 12 控件之EhLib 11.0.21 - D12 这个组合,解决的就是 Delphi 12 环境下数据网格、报表导出、单元格合并、下拉筛选这些基础能力从哪来的问题。EhLib 是 Delphi 生态里老牌的网格控件库,DBGridEh 几乎成了很多进销存、ERP 项目的标配。这篇就把 EhLib 11.0.21 在 Delphi 12 下的安装、接入、常用配置和踩坑点一次说透,适合刚升级到 Delphi 12、正被控件兼容性折磨,或者新项目打算选型网格控件的开发者。文章里不会贴官方文档,全部是我实际配置和维护项目时验证过的做法。

2. 装之前先看清版本:EhLib 11.0.21 与 Delphi 12 的配套逻辑

2.1 为什么升级 Delphi 12 后很多老控件包集体失灵

Delphi 每个大版本发布时,RTL 和 VCL 的内部接口都有变动,尤其从 Delphi 10.4 到 11、12 这几代,编译器对 Unicode、泛型、接口引用的处理都做了调整。第三方控件如果没用对应版本的源码重新编译,安装进 Delphi 12 后最常见的结果是:IDE 能识别到安装包,但编译项目时直接报 “E2065 Unsatisfied forward or external declaration”,或者打开窗体时提示找不到类。这不是控件本身坏了,而是编译出来的 DCU 目标平台和当前编译器不匹配。

EhLib 之所以在 Delphi 12 下还能用,是因为它保留了完整的源码包,不像某些闭源控件只给编好的 BPL。只要拿到对应 Delphi 12 的源码头,自己重新编译安装即可。11.0.21 这个版本号对应的是 EhLib 官方为较新 Delphi 版本做的修正分支,里面针对 Delphi 12 的编译器指令、Unicode 字符串处理、新版本 VCL 的 TStyleManager 兼容性都做了适配。

用我自己的话说,EhLib 11.0.21 不是“装上去就能用”的控件,它需要你先理解版本配套逻辑:操作系统位数、Delphi 版本、控件源码分支三者必须对齐。比如 64 位 Windows 上装 32 位 Delphi,或者反过来,编译出来的包在 IDE 里加载时就会很别扭。

2.2 下载与安装前要核对的三处配置

在动手双击安装包之前,先花两分钟检查三件事,能省掉后面至少一小时排错时间。

第一件,确认你的 Delphi 12 是哪个 Update 版本。Delphi 12 有初始版和后续更新版,编译器版本号会变。EhLib 的源码里通常用条件编译指令区分,比如根据 VER 定义选择不同代码路径。查看方式是在 IDE 里依次点击 Help -> About,看显示的版本号,或者在命令行敲dcc32 --version。一般来说,11.0.21 对应的是较新的 Delphi 12 更新版,如果你的 IDE 是旧补丁版本,建议先把 IDE 更新到最新。

第二件,确认项目里是否引用了其它表格类控件,比如某些国产报表控件的网格、或者是其它第三方 Grid。EhLib 和这些控件可能存在 DFM 类名冲突,或者都注册了相似的属性编辑器。如果项目已经用了其它网格,建议先在一个隔离的测试环境里安装 EhLib,不要在旧项目里直接装,免得两个包互相覆盖注册信息,IDE 崩溃都没地方哭。

第三件,检查系统 PATH 里有没有多个 Delphi 版本残留。我遇到过一台机器上同时装了 Delphi 10.4 和 12,结果 EhLib 安装脚本自动找到了旧版的 BPL 路径,编译时跑到旧版本的库目录里去链接了。这种问题表现很怪:编译提示找不到文件,但 IDE 又显示控件已装好。建议安装前手动确认注册表里HKCU\Software\Embarcadero\BDS\12.0的路径项只指向当前版本。

这三项检查做完,再进入安装环节就不会手忙脚乱。顺带说一句,EhLib 官方安装包里通常带 install 脚本,但那个脚本在 Delphi 12 下偶尔会抽风,自动识别路径失败。我更推荐手动编译和安装,虽然多敲几条命令,但每一步的报错都能看懂,出了问题好定位。

3. 把 EhLib 11.0.21 装进 Delphi 12:从 BPL 到 IDE 面板

3.1 安装路径与 Library 路径设置

拿到 EhLib 11.0.21 源码包后,先解压到一个干净的目录,比如D:\Components\EhLib。注意路径里不要带中文、不要带空格,Delphi 的旧版编译器对带空格的路径处理得很糟,虽然新版好一些,但没必要在这种地方赌运气。解压后打开目录,会看到按编译器版本划分的子目录,常见的是Delphi12或D12文件夹,源码主目录下则放着Common、Library等公共代码。

第一步先配置 IDE 的库路径。打开 Delphi 12,菜单栏选择 Tools -> Options -> Language -> Delphi -> Library,在 Library path 里加入 EhLib 源码目录下的几个关键子路径,包括公共源码目录和对应 D12 的目录。这一步是为了让编译器在编译项目时,能按文件名找到 EhLib 的各单元。

配置库路径的另一个容易被忽略的点:64 位和 32 位平台要分别加路径。Library path 界面上方有平台切换下拉框,默认显示 32 位 Windows,但很多新项目已经改成 64 位编译了。如果只配了 32 位路径,切到 64 位编译时又找不到单元,这就是新手经常说的“玄学报错”。我一般会把两个平台的路径都加上,省得后面忘。

路径配置好之后,接着安装运行期包。用 IDE 自带的资源管理器打开的安装方式,已经不是这个时代最可靠的做法了,我推荐直接用命令行编译。打开 Delphi 12 自带的命令提示符(在开始菜单里找 “RAD Studio Command Prompt”),这样环境变量是完整的,PATH 里已经包含 dcc32、brcc32 等工具。

cd /d D:\Components\EhLib\Delphi12 dcc32 -B -DDEBUG -JPHNE -M -R -Q -Y -Z -$D- -$L- -$Y- EhLibD12.dpk

这条命令编译的是运行期包,注意几个关键参数:-B表示全部重建,-DDEBUG定义 DEBUG 条件符号,-JPHNE生成 Delphi 兼容的 DCU 文件头,-M允许多目标平台,-R创建资源文件,-Q安静模式只显示错误。最后-$D- -$L- -$Y-是对应编译指令,关闭调试信息、局部符号和符号引用信息,让输出文件更干净。

编译完成后,同目录下会生成一个.bpl文件,比如EhLibD12.bpl。这是运行期包,需要被最终程序引用,但 IDE 设计期要加载的是另一个设计期包,通常是EhLibD12D.bpl(有些版本叫法不同)。接着编译设计期包:

dcc32 -B -DDEBUG -JPHNE -M -R -Q -Y -Z -$D- -$L- -$Y- EhLibD12D.dpk

编译好之后,在 IDE 里点击 Component -> Install Packages,选择 Add,把刚才生成的EhLibD12D.bpl加进去。正常情况下,工具栏的 Additional 或 Data Controls 分类下会出现 EhLib 相关的组件图标,包括 TDBGridEh、TDBEditEh、TDBLookupComboBoxEh 等。到这一步,安装环节就基本完成了。

需要注意的一点,编译输出的 BPL 文件目录要加入系统 PATH 或者 IDE 的 BPL 搜索路径,否则 Delphi 12 启动 IDE 时找不到设计期包,会弹窗提示 “BPL 文件不存在”。IDE 里在 Tools -> Options -> Library -> BPL path 里加一下即可。

3.2 设计期包与运行期包的区分以及安装顺序

很多人搞混设计期包和运行期包的区别,最后把一堆 BPL 全部安装在 IDE 里,IDE 启动越来越慢,项目编出来的 EXE 也异常大。这里用一句话解释:运行期包是程序运行时要加载的库,设计期包是 IDE 在设计界面上画控件时用的工具包。运行期包只跟最终程序有关,设计期包只跟 IDE 有关。

所以正确的安装顺序是:先编译运行期包,再编译设计期包;设计期包引入 IDE,运行期包则放进项目的 Runtime Packages 列表里。项目里引用 EhLib 时,可以在 Project -> Options -> Delphi Compiler -> Linking 里勾选 “Use runtime packages”,然后在列表里加上EhLibD12,这样 EXE 体积会小很多,依赖 BPL 发布即可。

但也需要提醒,运行时依赖 BPL 的发布方式有利有弊。好处是程序小、补丁更新容易,坏处是部署时容易漏掉 BPL 文件,目标机器上一运行就报 “无法找到 EhLibD12.bpl”。我建议正式交付给客户的系统,还是把 EhLib 静态链接进 EXE 更省心,也就是不勾选运行时包,让编译器直接把代码编进 EXE。代价是 EXE 体积会大 2 到 3 MB,但对现代电脑来说完全可以接受。

4. 上手最常用的 DBGridEh:属性、代码与三个必调参数

4.1 数据源绑定和常用显示属性

EhLib 装好后,用得最多的控件是 TDBGridEh,它跟标准 DBGrid 的外观看上去差不多,但多了很多企业级功能。新建一个窗体,放一个 TDataSource、一个 TClientDataSet 或者 TFDQuery,再放一个 DBGridEh,把 DataSource 串起来,就能先跑通一个最小展示。

和标准 DBGrid 的第一个差异是,DBGridEh 默认自带“标题栏点击排序”和“列筛选”的交互,但这些功能需要对应属性打开。先看几个必调属性:

  • DataSource:绑定数据源,这是所有数据网格的基础。
  • Columns:定义列集合,可以在设计期用列编辑器维护,也可以运行时动态添加。
  • AutoFitColWidths:设为 True 后,网络会自动按内容调整列宽,不会出现数据被截断的情况。
  • IndicatorOptions:控制行号指示器这一列,默认显示行号,但如果你不喜欢最左边的灰色区域,可以把gioRowsIndicator去掉。
  • OptionsEh:这是 EhLib 的灵魂属性,里面有很多子开关,后面细说。

在 DFM 文件里,DBGridEh 的OptionsEh是一个长属性,从老版本项目迁移过来的 DFM 经常因为选项不完全兼容导致编译报错。最常见的一种情况是,原来用dghAutoSortMarking这个选项,到了新版被改名了,编译直接提示无效属性值。遇到这种问题,处理方式不是硬改 DFM,而是先在一个空白窗体上放置新的 DBGridEh,把它生成的那段 OptionsEh 抄过去,再对照旧代码逐个调整业务逻辑。

在设计期维护列集合是个体力活,但值得做。选中 DBGridEh,右键点击 “Columns Editor”,可以添加、删除列;每一列可以独立设置FieldName、Title.Caption、Width、Alignment。这里最容易忽略的是列的Title属性下还有TitleButton开关,这个开关控制点击标题排序,默认是 False,不打开的话用户点击列标题没反应。

4.2 代码控制列宽、合计与排序

设计期配置适合静态界面,但真实项目里列都是根据用户权限和业务动态生成的。我在做某进销存项目时,就遇到过商品列表需要根据用户角色显示不同列的场景。这种情况一般用代码动态创建列。

procedure TForm1.BuildGridColumns; var Col: TColumnEh; begin // 先清空旧列,避免重复添加 DBGridEh1.Columns.Clear; // 第一列:商品编码 Col := DBGridEh1.Columns.Add; Col.FieldName := 'ItemCode'; Col.Title.Caption := '商品编码'; Col.Width := 80; Col.Alignment := taCenter; // 第二列:商品名称,设为自动撑满剩余空间 Col := DBGridEh1.Columns.Add; Col.FieldName := 'ItemName'; Col.Title.Caption := '商品名称'; Col.Width := 200; // 第三列:库存数量,右对齐更适合数字 Col := DBGridEh1.Columns.Add; Col.FieldName := 'StockQty'; Col.Title.Caption := '库存数量'; Col.Alignment := taRightJustify; Col.Width := 90; end;

这段代码的关键是TColumnEh这个类,它和标准 DBGrid 的TColumn不是同一类型,设计期列编辑器里能看到区别。FieldName要严格和数据集的字段名一致,如果字段不存在,运行时会显示空白而不是报错,这个坑经常让新手误以为是数据源问题。Alignment是三态属性,除了taLeftJustify、taCenter、taRightJustify之外,还有个taAuto,让 EhLib 根据字段类型自动决定对齐方式,数字右对齐、文本左对齐。我一般建议文本列用 taLeftJustify 或 taCenter,数字列统一 taRightJustify。

合计行是 DBGridEh 的招牌功能,比标准 DBGrid 方便太多。打开方式是设置FooterRowCount := 1,然后对需要合计的列的Footer.Value属性做配置。可以用设计器,也可以用代码:

// 在数据源 AfterOpen 事件里设置合计字段 procedure TForm1.DataSource1AfterOpen(Sender: TObject); begin // 显示底部合计行 DBGridEh1.FooterRowCount := 1; // 对数量列做合计,ValueType 设为 vtSum DBGridEh1.Columns[2].Footer.ValueType := vtSum; DBGridEh1.Columns[2].Footer.DisplayFormat := '#,##0.00'; // 对金额列按百分比计算,ValueType 使用 vtAvg DBGridEh1.Columns[3].Footer.ValueType := vtAvg; DBGridEh1.Columns[3].Footer.DisplayFormat := '#,##0.00'; end;

Footer.ValueType支持vtSum、vtAvg、vtCount、vtMax、vtMin等常见聚合,还包括vtFieldValue这种显示首行或末行字段值的选项。注意vtSum只对数值字段有效,如果字段是字符串,合计会默认显示 0,而不是报错。DisplayFormat用来控制合计数字的格式,要跟列的DisplayFormat保持一致,不然会出现表格里显示 1234.5、合计行显示 1234.50 这种不统一的细节问题,客户看见了会追问一句“怎么不一样”,解释成本很高。

排序这个功能,DBGridEh 默认支持点击列标题排序,但前提是数据集本身支持排序。如果是 TClientDataSet,直接设置IndexFieldNames属性即可;如果是 TFDQuery,需要在 SQL 里加 Order By 的动态拼写。DBGridEh 有个SortLocal属性,设置为 True 时可以在内存里对当前已加载的数据排序,不用重新查库。对于数据量不大的窗体,这个属性非常实用。但是一旦数据量超过几万行,内存排序会明显卡顿,这时候应该改成服务端排序。我在一个项目里用 SortLocal 排序两万行数据,界面直接卡了 4 秒,后来改成 Order By 才解决。

4.3 汉化按钮和右键菜单的落地方法

EhLib 自带了很多 UI 元素,比如列筛选下拉框里的 “全选”、排序提示、导出对话框里的按钮。这些默认是英文的,国内项目第一次跑起来都会觉得别扭。汉化这个事,很多人折腾半天没找到入口。实际上 EhLib 提供了一个全局语言资源单元,只要调用一个函数即可切换。

uses EhLibLangConsts; procedure TForm1.FormCreate(Sender: TObject); begin // 加载简体中文语言包 EhLibSetLanguage('CHS'); end;

EhLibSetLanguage函数位于EhLibLangConsts单元里,对应的语言常量定义在 EhLib 源码的EHlibLanguage文件夹下,里面有ChineseSimple.pas这个文件。调用这一行之后,DBGridEh 内置的对话框按钮、右键菜单默认项、筛选下拉框提示都会变成中文。要注意的是,这个调用必须放在所有窗体创建之前,或者放在主窗体的OnCreate事件里且早于任何 DBGridEh 的创建。如果你在子窗体已经打开之后再调用,已经创建好的控件不会刷新语言资源,需要重新创建控件才生效。

除了系统自带的英文菜单,很多项目会自己给 DBGridEh 加右键菜单,比如“刷新、导入、导出、打印预览”。右键菜单的做法是写一个 TPopupMenu,然后设置 DBGridEh 的PopupMenu属性。这里有个连很多老手都会忽略的细节:DBGridEh 在用户右键点击时,默认会先处理自己的内部菜单(比如排序、筛选),如果OptionsEh里的dghShowRecNo某些选项开着,内部菜单会覆盖你的 PopupMenu。解决办法是把OptionsEh的dghAutoSortMarking、dghFiltering等选项关掉,或者在 DBGridEh 的OnContextPopup事件里动态决定是否弹出自定义菜单。

procedure TForm1.DBGridEh1ContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean); begin // 始终使用自定义菜单,屏蔽 EhLib 内置菜单 PopupMenu1.Popup(Mouse.CursorPos.X, Mouse.CursorPos.Y); Handled := True; end;

Handled设置为 True,相当于告诉 DBGridEh “这个右键事件我已经处理了,你不用再弹你自己的菜单”。这里还要注意Mouse.CursorPos和参数里MousePos的区别,MousePos是相对于 DBGridEh 左上角的坐标,自定义菜单用屏幕坐标定位更准确,所以用Mouse.CursorPos。如果菜单一直弹不出来,排查这个参数是第一步。

5. 避坑指南:EhLib 11.0.21 在 Delphi 12 下的五个常见翻车点

5.1 现象:DFM 报错“Class TDBGridEh not found”

这是从旧项目升级到 Delphi 12 后最常遇到的错误。打开窗体时 IDE 弹出一个错误框,提示Class TDBGridEh not found,或者窗体上那个网格位置显示成一个灰块,上面写着一行小字。这个问题的直接原因是当前 IDE 没有加载包含 TDBGridEh 的设计期包,也就是前面说的那个EhLibD12D.bpl。

原因通常有两种。第一种是设计期包没有被正确安装,可以参考第三章的步骤重新编译安装,然后确认 IDE 的已安装包列表里勾选了那个 BPL。第二种是安装时路径配错,比如 BPL 文件被安装到硬盘的某个位置,但 IDE 启动时根据 BPL path 搜索不到,于是设计期包加载失败。这种情况下 IDE 菜单里显示的包名是灰的,或者干脆不出现。

解决方法是,首先在 IDE 的 Component -> Install Packages 里看当前包列表,找到 EhLib 相关项,取消勾选再重新勾选一次。如果依然报错,打开 Windows 的资源监视器,确认EhLibD12D.bpl文件确实存在于硬盘上,且被 IDE 搜索到了。还有一个隐蔽问题:64 位 IDE 和 32 位 BPL 不匹配。Delphi 12 默认的 IDE 进程是 32 位还是 64 位,取决于安装版本,如果你下载的 BPL 是 64 位而 IDE 是 32 位,同样会报这个错。检查 BPL 的位数,可以用记事本打开 BPL 看到 PE 头标记,但更简单的方法是在命令行下运行dumpbin /headers EhLibD12D.bpl | findstr machine,输出x64表示 64 位,x86表示 32 位。

5.2 现象:IDE 打开窗体卡死或报 Access Violation

这个现象在新装 EhLib 后非常常见:打开包含 DBGridEh 的窗体,IDE 直接没有响应,过一会儿报Access violation at 0x...,然后 IDE 的窗体设计器崩溃。相比前一个问题,这种卡死更像“玄学”,但实际上原因基本有几个固定的。

第一个原因是 DFM 文件里包含了旧版本 EhLib 的遗留属性。比如旧版本里有Title.Overflow之类的属性,新版已经移除,设计器解析时访问了一个已被释放的对象,就直接崩溃。解决方法是不要用 IDE 直接打开这个窗体,而是先用文本编辑器打开 DFM,把 DFM 里 EhLib 相关的属性段和旧版对比、手动删除不兼容的键值。DFM 是文本格式,可以用记事本打开,把object DBGridEh1到end之间的一段复制出来单独保存,在一个干净的窗体里逐步把属性加回去,找到导致崩溃的那个属性就删掉它。

第二个原因是字体问题。Delphi 12 的 IDE 默认字体和缩放跟老版本不同,DBGridEh 在设计时如果取了不存在的字体名称,VCL 的字体枚举可能会死循环。把窗体上 DBGridEh 的Font.Name统一改成在系统里确定存在的字体,比如Microsoft YaHei UI或Tahoma。这个看起来和“崩溃”扯不上关系,但确实是老项目升级里一个高频翻车点。

第三个原因是 EhLib 包和某个三方控件包的属性编辑器冲突。如果你在 IDE 里装了其它带网格属性编辑器的包,两者可能同时注册了同一个属性名,打开窗体时属性编辑器互相覆盖导致崩溃。这种情况比较难查,最稳妥的办法是在一个干净的虚拟机或者另一台开发机上只装 EhLib 测试,如果问题消失,基本确定是包冲突。

5.3 现象:编译通过但运行时找不到 BPL

这个问题的场景很典型:开发机上程序运行得好好的,拷到另一台机器上双击 exe,系统弹窗说无法找到 EhLibD12.bpl。这是因为项目里启用了运行时包(Runtime Packages),exe 运行时动态加载 BPL。开发机上 IDE 的搜索路径能找到 BPL,但目标机器上没装开发环境,自然找不到。

解决这个问题有两个方向。第一个方向是关闭运行时包,也就是在 Project -> Options -> Delphi Compiler -> Linking 里,把 “Use runtime packages” 前面的勾去掉。这样编译器会把 EhLib 的代码直接编进 exe,发布时只需要带上 exe 文件。这个方法最简单,但缺点是每次修改都需要重新编译整个项目。

第二个方向是保留运行时包,但把 BPL 文件和 exe 放到同一目录下一起发布。还有一个建议:即便用运行时包发布,也不要依赖系统 PATH 去搜索 BPL,而是把需要的 BPL 复制到 exe 同目录下,程序启动时会优先在当前目录查找。BPL 列表里除了EhLibD12.bpl,往往还依赖VCL.bpl、rtl.bpl这些 Delphi 运行库,它们通常已经包含在 Delphi 的安装目录里,如果你在发布时只带了一个EhLibD12.bpl而忽略了基础库,程序同样无法启动。最省事的做法是把整个 BPL 目录都复制过去,只留那一个 exe 并不会减少文件数量。

5.4 现象:字体和排版在 125% 或 150% 缩放下错位

这个问题在 Windows 高分屏下特别明显。开发机的显示缩放是 100%,打包好的程序拷到客户的 2K 屏幕上,界面里的文字挤成一团,DBGridEh 的行高和列宽逻辑混乱,合并单元格错位。这不是 EhLib 独有的问题,是 Delphi VCL 程序在高 DPI 下的通病,但 DBGridEh 的表现尤其明显,因为它的绘制逻辑里写了很多基于像素的坐标计算。

解决方案分两个层面。第一层面是在程序入口处理 DPI 感知,在项目文件(dpr)的 program 段最前面,调用 SetProcessDpiAwarenessContext 或声明高 DPI 支持。一个完整的 dpr 头部改成这样:

program MyApp; uses Winapi.Windows, Vcl.Forms, Vcl.Themes, MainForm in 'MainForm.pas' {Form1}; {$R *.res} begin // 告诉系统这个程序自己处理 DPI 缩放,防止字体模糊 SetProcessDPIAware(); Application.Initialize; Application.CreateForm(TForm1, Form1); Application.Run; end.

SetProcessDPIAware()来自 Windows API,调用后系统会把程序当作 DPI 感知来处理,不再强制拉伸位图,字体会保持清晰。但这样一来,我们自己的代码要承担缩放适配工作,否则窗体出了 200% 缩放的机器,还是会被系统缩放。

第二层面是让 DBGridEh 的字体随系统缩放。做法是在窗体OnCreate里读取当前系统的字体缩放比例,按比例调整 DBGridEh 的Font.Size和RowHeight。如果网格的字体调大,但行高没有跟着变,文字会被裁切,所以两个属性要一起改。

5.5 现象:升级项目后中文标题乱码

老项目从 Delphi 7 或 Delphi 2007 迁过来时,DFM 文件里的中文标题经常出现乱码,DBGridEh 的列标题、按钮文字都变成一串问号或者繁体乱码。这是编码格式的问题:旧版 Delphi 的 DFM 是 ANSI 编码,Delphi 12 强制按 UTF-8 解析,所以中文字符被错误解释。

解决方法是统一把 DFM 文件转成 UTF-8 格式。在 IDE 里,右键点击 DFM 文件,选择 “Add to Project” 旁边的下拉框,有一个 “Save As UTF-8” 的选项。也可以直接在项目里把所有 DFM 文件的格式统一调整。注意转换后要检查一遍所有中文标题,特别是 DBGridEh 的列标题和 Footer 合计行的文字,因为有些字符在 ANSI 和 UTF-8 之间来回转换后会丢失。

另一个相关问题是代码文件(.pas)的编码。如果 .pas 文件里直接写了中文字符串,但文件本身是 ANSI,编译时 Delphi 12 会按 UTF-8 读,字符串常量里的中文会变成乱码,运行时显示在 DBGridEh 的列标题里也就乱了。处理办法是在 IDE 里打开 .pas 文件,菜单 File -> Save As 时选择 UTF-8 编码。牢记EhLibSetLanguage('CHS')这行本身也要放在一个 UTF-8 编码的文件里,否则那个 'CHS' 字符串倒无所谓,但函数名如果被损坏了,编译直接报错,排错时很容易让人怀疑是 EhLib 不兼容,实际是文件编码问题。

6. 进阶技巧:用官方 Demo 逆向学 EhLib 11,把排查效率提上去

EhLib 11.0.21 的源码包自带一整个 Demo 目录,里面是各种控件用法的最小示例。很多人装完控件就关掉了 Demo 文件夹,这是个巨大损失。与其在网上到处搜索属性用法,不如直接把 Demo 跑起来,边改边看效果。我维护一个老 ERP 的时候,就是靠把 Demo 里的GridTester项目跑起来,才彻底搞懂了DBGridEh的OptionsEh里几十个子开关的相互作用。

具体操作方法是:打开 Demo 目录下的项目文件,先编译运行,然后用它对照你的需求。比如你想做单元格合并,就在 Demo 里找带Merge字样的示例窗体,把它的OptionsEh抄到你的项目里。Demo 项目大多有运行期调试界面,可以直接在运行中改网格属性、切换选项,实时看效果。这个方法比“设一个属性编译一次、看一次”的效率高一个数量级。我习惯把 Demo 项目编译成独立 exe,放在手边随时研究,遇到具体问题就用搜索引擎搜那个属性名的组合。

还有一个技巧点,是用 DBGridEh 的导出功能做项目交付。很多客户会要“导出 Excel 功能”,如果项目里自己写 Excel 导出,通常要引入 COM 或者第三方库,部署很麻烦。DBGridEh 内置了SaveToXLS方法,一行代码就能把网格内容导出成 Excel 格式:

// 导出当前网格数据到 Excel 文件,弹出保存对话框后自动写文件 DBGridEh1.SaveToXLS('C:\Temp\export.xls', True);

第二个参数IsShowDialog意思是先弹一个保存对话框让用户选位置。需要注意的是,这里的 XLS 是 OLE 老格式,Excel 能打开但体积比较大;如果客户要求 .xlsx,需要改用SaveToXLSX方法。这两个方法都不依赖 Excel 组件,后台进程不需要装 Office,在服务器上跑导出任务也很稳。这个细节是我在某个项目里被甲方问“服务器能不能导出”时,临时翻 Demo 源码发现的,后来成了标准交付方案的一部分。

还有一个小技巧是善用OnGetCellParams事件来做动态行着色。比如库存低于安全线的商品要标红,在 DBGridEh 里不需要画自定义单元格,只需在这个事件里根据数据状态设置字体颜色和背景色:

procedure TForm1.DBGridEh1GetCellParams(Sender: TObject; EditMode: Boolean; Params: TCellParamsEh); begin // 当库存数量字段小于 10 时,把当前单元格背景改为浅红 if VarIsNumeric(DBGridEh1.DataSource.DataSet.FieldByName('StockQty').Value) and (DBGridEh1.DataSource.DataSet.FieldByName('StockQty').Value < 10) then begin Params.Background := $00E8C8C8; // 浅红色背景 end; end;

TCellParamsEh是 EhLib 专门提供的一个参数类,用来临时覆盖当前单元格的绘制样式,不用改数据、不用设属性,性能开销非常小。通过这个事件还能做“数字负数显示红色”“关键行加粗”等需求,替换掉以前老项目里一层层画布绘制的复杂代码。我见过很多项目里用自定义 DrawColumnCell 画网格,代码又长又难维护,其实大部分需求都能被这个事件替代。

用真实需求驱动着去 Demo 里找答案,这是我用 EhLib 这些年最省时间的路。回看这一路,最开始我也是到处翻帖子、试属性,直到某天静下心把 Demo 完整跑了一遍,才觉得这个控件再没什么黑匣子。希望你装完之后先花半小时玩一遍自带的示例,能少走不少弯路。希望帮到你。

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

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

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

立即咨询