news 2026/10/22 7:57:44

Delphi 12.3下Ehlib 111015安装配置与DBGridEh高级应用指南

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Delphi 12.3下Ehlib 111015安装配置与DBGridEh高级应用指南

简介:Delphi 12.3环境下的Ehlib控件完整发布包,面向需要高级表格、数据库网格及灵活报表展示的桌面应用开发者,尤其适合正在升级IDE版本并延续控件使用的团队。压缩包内有2000个文件,以dfm窗体布局、pas单元源码、res资源及dproj、dpk、dpr工程文件为主体,另含ico、png图标与chm帮助文档,便于编译安装和接口查阅。资源总大小约32.7MB,文件类型覆盖设计期包、运行期包和示例工程,并提供了多个可编译示例用于验证控件在12.3下的兼容性,目录结构符合组件包常见组织方式。已有60人学习,适合中高级Delphi开发者参考。可直接研读源码理解EhLib网格控件的内部实现,也能将其安装到Delphi 12.3中使用高级表格、数据排序、分组统计等功能,减少自绘表格的重复开发成本。

1. Ehlib 111015:Delphi 12.3 数据表格场景里一直缺的那层能力

Delphi 12.3 的工程里,Ehlib 111015 是一个常被老开发优先装上的增强型表格控件包。原生 DBGrid 在排序、过滤、统计栏、导出这些需求面前有多被动,用过的人都清楚,而 Ehlib 大多只需要点几个开关。这份资源包里没有一键安装程序,需要自己用 IDE 包管理器编译;但配套的帮助文档、示例工程、位图资源都在,按下面步骤走,十五分钟内能让 DBGridEh 上窗体。它解决的是数据管理类桌面项目的四件套:本地排序、字段过滤、统计栏、批量导出。适合正在用 Delphi 12.x 做 MIS 或进销存类项目的开发者,也适合准备从原生 DBGrid 迁移到成熟组件的团队。

2. Ehlib 111015 下载解压后:文件清单、安装流程与两种 IDE 的边界

拿到压缩包第一件事不是双击安装脚本,而是先把文件分清楚。这类控件包和普通绿色软件完全不同,里面的位图、帮助文件、工程配置各有各的位置,乱动反而会埋雷。我一般会先建一个纯英文目录,比如D:\Libs\EhLib111015,然后整体解压,再按类型过一遍。

2.1 解开压缩包先分类:位图、帮助与 Demo 分别在哪

压缩包里能看到不少.bmp结尾的文件,比如ViewSourceBIN.bmp、NetworkWorkgroupTrans.bmp、tutorial2.bmp、delphixe.bmp,这些不是装饰图,而是控件在 IDE 里显示的图标资源,或者源码浏览器背景素材。编译时它们会被链接进设计期包,所以解压时不要只挑.dpk和.bpl,把整个目录结构保留好,尤其是 Resources、Images 这类子目录,缺失会导致包能编译但工具栏图标空白。

文件实际作用
EhLibHelp.chm离线帮助文档,安装前建议先读一遍
EHLIB.CNT帮助目录索引,配合 CHM 使用
Project1.bprC++Builder 示例工程文件
Project1.cppC++Builder 示例工程源码入口
Project2.cfg示例工程编译配置,包含平台参数
ViewSourceBIN.bmp 等位图IDE 工具栏或控件图标资源

Project1.bpr和Project2.cfg看起来不像 Delphi 文件,容易被当成杂物,实际上这是包内示例工程的 C++Builder 侧配置。如果你只用 Delphi,这两个文件不影响安装;如果团队里有人用 C++Builder,则要额外留意位宽和 VCL 组件继承关系。

2.2 Delphi 12.3 编译与安装:先挂 Library path,再编译包

常见做法是:先确认解压后的包里有源码目录,再走 IDE 的 Library 配置。不要把.bpl文件直接拷到 Windows 系统目录,那只会让多个版本互相打架。

  1. 打开 Delphi 12.3,进入Tools > Options > Delphi Options > Library,把解压目录下的源码目录加到Library path。这里注意,路径不要带中文,也不要带空格。很多离奇编译错误都出在路径解析上。

  2. 打开Component > Install Packages,先看右侧已安装包列表里有没有 EhLib 相关项。如果有旧版本,先卸载,再点击Add按钮,指向解压目录下已编译好的设计期包.bpl。

  3. 如果压缩包里没有现成的.bpl,就要用源码编译。在 IDE 里打开源码目录中的.dpk包工程文件,一般会看到运行期包和设计期包两类。先编译运行期包,再编译设计期包,最后右键设计期包选择Install。

  4. 关闭并重启 IDE,左侧组件面板里出现 EhLib 相关组件页,安装才算结束。

注意:包内没有一键安装程序,所有安装操作都要通过 IDE 的 Package 管理器完成,挂 Library path 只是第一步。编译顺序错是最常见的翻车点,先设计期包后运行期包,几乎必报依赖缺失。

2.3 C++Builder 使用者注意:.bpr 与 .cfg 对应另一条安装线

如果你拿到包后习惯性用 Delphi 打开Project1.bpr,会直接提示无法识别工程。Project1.bpr是 C++Builder 的工程文件,Project2.cfg则是编译器配置,包含目标平台、输出目录等参数。这两个文件的存在说明资源包里附带的 Demo 是跨 IDE 的,至少覆盖了 RAD Studio 下的 C++ 侧。

C++Builder 侧安装时,我一般会先确认当前项目是 32 位还是 64 位,再把.bpl安装到对应 IDE 版本。若直接在 64 位设计期里加载 32 位包,IDE 会静默跳过,组件面板里什么都看不到。另一个容易忽略的是Project2.cfg里的-LU参数,它指定了链接的运行期库,如果和实际编译选项不一致,链接阶段会报“不能解析外部符号”。

3. DBGridEh 参数配置三件套:数据接入、排序过滤、统计栏与下拉列

组件装上以后,真正的效率提升在属性配置。Ehlib 的价值不是多了一个网格控件,而是把大量前端交互能力直接塞进了设计期属性里。我每次接新项目,都会按数据接入、排序过滤、统计栏、列类型四条线逐项过一遍。

3.1 数据接入这项先做对:DataSource 与数据集选型

DBGridEh 本身只是显示层,它依旧通过DataSource读取数据。很多新手把它当成自带数据库连接的控件,这是误解。正确接法是先建数据集,再挂 DataSource,最后把 DBGridEh 的 DataSource 指过去。

FDQuery1.Connection := FDConnection1; FDQuery1.SQL.Text := 'select id, name, amount, create_date from orders order by id'; FDQuery1.Open; DataSource1.DataSet := FDQuery1; DBGridEh1.DataSource := DataSource1;

这段代码的逻辑很直接:先给FDQuery1指定数据库连接和查询语句,然后Open打开数据集,最后把DataSource1和DBGridEh1串起来。DBGridEh1本身不做数据访问,所以数据集选什么类型都行,TFDQuery、TClientDataSet、TADOQuery 都能用。

参数说明:FDQuery1用 FireDAC 访问数据库,适合新工程;老项目用 ADO 也完全可以,DBGridEh 对 TDataSet 后代兼容得很好。关键点是DBGridEh1.DataSource不能为空,运行时一旦数据集关闭,网格内容会直接清空。

3.2 OptionsEh 一揽子开关:先理解排序与过滤的本地方案

Ehlib 最强的两个交互是本地排序和本地过滤。所谓本地,是指数据集已经打开的前提下,网格直接在前端完成排序和筛选,不需要重新回数据库执行 SQL。这对单表数据量在十万行以内的桌面场景非常实用。

我一般会这样设置:

DBGridEh1.SortLocal := True; DBGridEh1.FilterLocal := True; DBGridEh1.OptionsEh := DBGridEh1.OptionsEh + [dghAutoSortMarking, dghMultiSortMarking, dghIncSearch];

SortLocal := True表示用户点击列头时,网格在内存中对当前数据集排序;FilterLocal := True允许用户在列头下拉框输入筛选条件,网格按当前字段值过滤。OptionsEh是集合属性,里面对应一组开关,dghAutoSortMarking负责在列头显示排序箭头,dghMultiSortMarking支持按住 Ctrl 多列排序,dghIncSearch开启输入即定位,用户敲字母直接跳到匹配行。

这里的排序和数据库索引是两码事。本地排序面向的是已经 Select 出来的结果集,如果数据量特别大,还是应该回数据库做分页和排序,不要在网格里一次性加载百万行再本地排,内存会先撑不住。

3.3 统计栏与页脚合计:不写 SQL 也能出 SUM

业务报表里最常见的底部合计,原生 DBGrid 要自己写页脚绘制,Ehlib 在属性层面直接支持。先把网格的FooterRowCount设为 1,然后对指定列设置Footer.ValueType。

DBGridEh1.FooterRowCount := 1; DBGridEh1.Columns[3].Footer.ValueType := 'SUM'; DBGridEh1.Columns[3].Footer.FieldName := 'AMOUNT'; DBGridEh1.Columns[3].Footer.DisplayFormat := '#,##0.00';

FooterRowCount控制底部显示几行统计行;Footer.ValueType可选'SUM'、'COUNT'、'AVG'等内置聚合类型;FieldName指定要对哪个字段做统计;DisplayFormat则格式化成千分位小数。这套合计计算的是当前数据集内可见行,也就是说过滤之后,合计值会自动跟着筛选结果变化,不用重新 SQL 聚合。

提示:如果业务要“过滤前合计、过滤后也要合计”,可以再配合OnGetFooterValue事件自定义统计值。系统默认合计只会作用在过滤后的行集上,理解这一点能避免不少报表数据对不上的问题。

3.4 下拉、日期、复选框:三类高频列配置一次讲清

网格里常见的下拉选择、日期选择、布尔展示,在 Ehlib 里都能通过列属性配置,不用每列画单元格编辑器。日期列一般设置Column.ButtonStyle为下拉风格,点击列单元格右侧出现小三角,弹出日历选择器。

DBGridEh1.Columns[4].ButtonStyle := cbsDropDown; DBGridEh1.Columns[4].EditButtons[0].Style := ebsEllipsis;

ButtonStyle控制列的编辑按钮外观,cbsDropDown代表下拉按钮样式;接着给该列添加一个省略号编辑按钮,点击后可以弹出自定义选择窗体。布尔字段则可以在字段对象的KeyList和DisplayValues上做映射,网格会自动显示为复选框或“是/否”文本。

下拉列表还有一种更轻量的做法,直接在列属性的PickList里手动填几个静态值,适合状态字段,比如“待审核、已审核、已驳回”。这种方式不涉及数据库外键表,写死在设计期,改起来也方便。

4. 实战里的三个封装套路:基类复用、动态生成列、导出不依赖第三方控件

安装配置只是开始,真正让 Ehlib 发挥价值的是封装方式。如果每个窗体都从组件面板拖一个 DBGridEh、配一遍属性,会有大量重复操作。我习惯把通用逻辑收敛到一个基类里,这样后续新增窗体只需要继承。

4.1 统一基类封装:空数据、异常、加载状态一次管住

先创建一个继承自TForm的基窗体,放好TFDQuery、TDataSource、TDBGridEh,然后写一个统一的LoadData方法。这样所有业务窗体都走同一条数据加载路径,异常处理也集中在一处。

type TBaseGridForm = class(TForm) FDQuery1: TFDQuery; DataSource1: TDataSource; DBGridEh1: TDBGridEh; public procedure LoadData(const ASQL: string); virtual; end; implementation procedure TBaseGridForm.LoadData(const ASQL: string); begin FDQuery1.Close; FDQuery1.SQL.Text := ASQL; try FDQuery1.Open; except on E: Exception do begin DBGridEh1.DataSource := nil; MessageDlg('数据加载失败:' + E.Message, mtError, [mbOK], 0); end; end; end;

这段代码的逻辑重点在异常处理。数据库连接不稳定时,Open抛出的异常如果没被捕获,窗体上会弹一个默认错误框,界面可能卡在半加载状态。这里先把DBGridEh1.DataSource置空,避免网格显示残留数据,再给用户一个明确提示。

参数说明:ASQL是调用方传入的查询语句;virtual关键字允许子类重写加载逻辑。基类里只负责通用流程,具体业务 SQL 由子窗体传入,减少重复的连接配置代码。

4.2 动态列生成:接口字段不固定时的兜底方案

有些报表接口返回的字段是动态的,设计期没法预先拖列。此时可以在数据集打开后,按照字段集合动态创建列,保证网格不会空白。

procedure TBaseGridForm.BuildColumnsByField; var i: Integer; Col: TColumnEh; begin DBGridEh1.Columns.Clear; for i := 0 to FDQuery1.FieldCount - 1 do begin Col := DBGridEh1.Columns.Add; Col.FieldName := FDQuery1.Fields[i].FieldName; Col.Title.Caption := FDQuery1.Fields[i].DisplayLabel; end; end;

这里用DBGridEh1.Columns.Add创建新列,比手动TColumnEh.Create更安全,列会自动挂到网格的列集合上。FieldName指定列对应的数据集字段;Title.Caption取字段的DisplayLabel,这样字段在数据字典里配置过中文名后,网格标题自动显示中文,不需要额外翻译映射。

4.3 Excel 导出:先看帮助文档再选 API,少走弯路

Ehlib 自带导出能力,不用额外引第三方组件。官方帮助文档EhLibHelp.chm里对导出 API 有专门章节,不同小版本方法名会有差异。常见做法是先调用派生列的保存方法,再根据导出文件类型决定是否传格式参数。

procedure TBaseGridForm.ExportToExcel(const AFilePath: string); begin if DBGridEh1.DataSource = nil then raise Exception.Create('没有可导出的数据源'); DBGridEh1.SaveToXLS(AFilePath); end;

先判空DataSource,避免用户没加载数据直接点导出,产生一个空表文件。SaveToXLS是较为常见的导出方法名,部分版本里叫ExportGridToFile,不确定时打开 CHM 帮助文档搜索导出关键词,以帮助页面里的签名优先。导出后建议再用ShellExecute打开目标文件,让用户立刻看到结果,体验会好很多。

5. 避坑指南:Delphi 12.3 安装使用 Ehlib 的五个翻车现场

控件包的坑一般不在功能上,而在版本匹配和安装顺序上。这里写的几条都是实际过程中反复遇到的高频问题,每一条都是现象、原因、解决三步走。

5.1 编译期报缺 dclEhLib.dcp:先运行期包后设计期包

现象:打开设计期包工程后按编译,IDE 报找不到dclEhLib.dcp或类似 DCP 文件。

原因:编译顺序反了。设计期包依赖运行期包先编译出的 DCP 文件,如果直接编译设计期包,依赖缺失就会报错。

解决:先打开运行期包工程并编译,确认输出目录生成了.dcp文件后,再编译设计期包。同时检查Tools > Options > Delphi Options > Library里是否把运行期包输出目录加进查找路径。

5.2 拖拽到窗体 IDE 闪退:多数是旧包残留或未重启

现象:安装完成后,把 DBGridEh 拖到窗体上,IDE 直接崩溃或无响应。

原因:机器上装过多个 Ehlib 版本,旧的.bpl还留在已安装包列表里,运行时多个包内同名类冲突,拖拽触发注册表加载时崩溃。

解决:先备份当前工程,打开Component > Install Packages,把旧的 EhLib 相关包全部卸载,关闭 IDE,删除临时目录里的旧编译缓存,重新打开 IDE 再安装新包。安装后必须重启一次 IDE,不要嫌麻烦。

5.3 运行后提示 Class TDBGridEh not found:看 Run-Time Packages 设置

现象:开发环境编译运行正常,把程序拷贝到别的机器后,启动报找不到TDBGridEh类。

原因:工程勾选了Build with runtime packages,生成的 EXE 不包含控件运行期代码,运行时需要对应的.bpl文件,而目标机器没有这些包。

解决:要么在Project > Options > Packages里取消运行期包勾选,让控件静态链接进 EXE;要么把依赖的.bpl一起拷贝到 EXE 同目录。维护工具类程序我会偏向取消运行期包,发布文件简单,不依赖目标机器环境。

5.4 中文变方块与字体错乱:主题和字体分开设置

现象:表头中文显示为方块,或者字体忽大忽小,看起来像换了台电脑后的渲染问题。

原因:DBGridEh 默认字体可能与系统主题不匹配,尤其是开启了深色模式或缩放比例非 100% 的机器上,旧字体无法正确处理中文。

解决:在FormCreate里统一设置DBGridEh1.Font.Name := 'Microsoft YaHei',同时单独设置DBGridEh1.Title.Font。不要只改网格同一个Font后就不管,标题字体和正文字体是两套属性。遇到深色主题还想保留网格白底的,可以把StyleElements里的seFont排除,避免主题强制改字体颜色。

5.5 Demo 的 .bpr 打不开:别在 Delphi 里硬碰 C++Builder 工程

现象:用 Delphi 打开Project1.bpr提示无法识别工程。

原因:.bpr是 C++Builder 专用工程文件,Project2.cfg也是 C++ 编译器配置,Delphi 没有对应加载逻辑。

解决:纯 Delphi 场景忽略这两个文件,直接使用帮助文档和.dpk源码。C++Builder 使用者打开工程前,先确认目标平台和当前 IDE 位宽,32 位工程不要用 64 位配置编译。这个文件和“垃圾文件”无关,是跨语言 Demo 的一部分。

6. 最后一个用得上的技巧:OnGetCellParams 做数据预警着色

状态类报表里的数据预警,一直是界面开发里最琐碎的部分。库存低于阈值要标红,金额为负要变黄,评分过低要加粗,这些如果散落在各个控件事件里,后期维护会非常难受。Ehlib 的OnGetCellParams事件就是专门解决这个问题的,它可以统一根据字段值修改当前单元格的字体和背景色。

procedure TForm1.DBGridEh1GetCellParams(Sender: TObject; Column: TColumnEh; AFont: TFont; var Background: TColor; State: TGridDrawState); begin if Column.FieldName <> 'STOCK' then Exit; if DBGridEh1.DataSource.DataSet.FieldByName('STOCK').AsInteger < 10 then begin Background := $00E8C8C8; AFont.Color := clMaroon; AFont.Style := AFont.Style + [fsBold]; end; end;

这段代码先判断当前列是不是STOCK字段,不是就直接退出,避免每画一个单元格都做无谓的取值判断。然后读取当前行该字段的值,小于 10 时把背景色改为浅红,字体改成深红并加粗。State中如果包含gdSelected,说明当前行处于选中状态,这时若直接改背景色,会覆盖系统的选中色,导致看不出哪行被选中。

一个更稳妥的习惯是在事件开头加一句if gdSelected in State then Exit;,让选中行保持原有的高亮样式。这样无预警字段、选中行、正常行三条分支互不干扰。对于想要显示图标的情况,逻辑也是一样的,判断字段后设置Column.ImageIndex即可,底层走的还是同一套逐格绘制机制。

这个事件还有一个好处:不侵入数据模型。无论数据集来自查询还是内存表,显示层只做颜色映射,字段值本身不会被改动。二十几个字段的报表,只要在事件里写几个分支,就能把异常数据全部捞出来,比在每条数据加载后写循环判断要直观得多。

从那以后,我每次把 Ehlib 装进新环境,都强制先跑一遍GetCellParams的变色逻辑,它比任何功能清单都能验证包、依赖和绘制链路是否正常。希望这份从安装到避坑的记录能帮到你。

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/22 7:55:44

博客系统重构实战:从Django到MySQL与Redis的工程化升级

在软件学院创新实训的第二阶段&#xff0c;我没有换新题目&#xff0c;而是选择把上一轮做的个人博客推翻重写&#xff0c;于是便有了这个项目代号“个人博客2”。说是“2”&#xff0c;其实更像一次脱胎换骨的重构&#xff1a;第一版能跑&#xff0c;但数据模型混乱、渲染层把…

作者头像 李华
网站建设 2026/10/22 7:55:38

Function Calling实战指南:让大模型安全接入业务系统

先说结论&#xff1a;Function Calling 是当前把大模型真正接进业务系统时&#xff0c;性价比最高、落地最快的一项能力。它不改变模型的训练方式&#xff0c;也不需要你微调一个专用模型&#xff0c;只需要在请求里多传一份“工具清单”&#xff0c;让模型学会在你设定的规则下…

作者头像 李华
网站建设 2026/10/22 7:54:09

微信小程序警务辅助系统设计与实战

简介&#xff1a;本资源是一套面向计算机专业本科生的毕业设计级微信小程序实战项目&#xff0c;聚焦警务辅助人员管理场景&#xff0c;适用于课程设计、毕设选题与Java小程序全栈开发能力提升。系统基于微信开发者工具开发&#xff0c;前端采用WXML/WXSS/JS构建轻量交互界面&a…

作者头像 李华
网站建设 2026/10/22 7:53:39

Java环境下YOLO实时目标检测与行为分析全流程实战

在Java技术栈里跑YOLO&#xff0c;很多人第一反应是“这不自找麻烦吗”。毕竟AI这圈子几乎被Python统治&#xff0c;Java充其量在业务层打打辅助&#xff0c;调调接口、传传参数。 但我今天要说的是&#xff1a;Java完全能扛起实时目标检测这摊活&#xff0c;而且还能在检测结…

作者头像 李华
网站建设 2026/10/22 7:53:39

AI对话App接入TTS语音:从状态管理到音频焦点的完整落地避坑指南

直接开门见山&#xff1a;带TTS语音的AI对话App&#xff0c;看起来就是个“聊天界面语音播放”&#xff0c;真做起来坑一点不比业务逻辑少。我从语音唤醒、流式文字回复、合成音频播放、到界面状态同步&#xff0c;整个流程走了一遍&#xff0c;中间踩了不少细节问题&#xff0…

作者头像 李华
网站建设 2026/10/22 7:51:56

LLM智能体可靠性设计:冗余执行从原理到工程落地

你们有没有遇到过这种情况&#xff1a;一个AI智能体&#xff0c;开发的时候测试集跑得漂漂亮亮&#xff0c;一上线就被真实数据打得措手不及。不是代码逻辑有bug&#xff0c;而是藏在链路里的某次LLM调用&#xff0c;这次结果是对的&#xff0c;下次结果是错的&#xff0c;毫无…

作者头像 李华