ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

EhLib 11.0.21适配Delphi 12.3:数据网格增强与高DPI兼容实践

EhLib 11.0.21适配Delphi 12.3:数据网格增强与高DPI兼容实践 简介本资源是面向Delphi开发者的一套完整EhLib 11.0.21第三方控件库专为Delphi 12.3D12环境适配编译适用于中高级Windows桌面应用开发人员解决UI增强、数据网格优化、报表导出及多语言支持等常见企业级开发需求。压缩包共含2000个文件主体为518个dfm窗体设计文件、293个pas核心单元源码、196个dproj工程配置及170个dpk包定义文件辅以大量res资源、ico图标与doc/docx说明文档整体体积68.95MB结构规范、模块清晰便于直接集成或源码级二次开发。已有87人学习下载资源包含完整安装流程、示例工程含tutorial2、Project1等、多格式图标资源bmp、png、gif、jpg及本地化支持文件rus、gbk特别适合需要快速落地高兼容性界面组件的Delphi项目团队。1. EhLib 11.0.21 不是“又一个 VCL 控件包”它是 Delphi 12.3 下少数能真正接管数据呈现边界的底层增强层在 Delphi 12.3 的 IDE 中拖入一个TDBGrid你立刻会意识到原生网格对空值显示、行高自适应、列冻结、多级表头、导出 Excel 格式控制——全靠手写OnDrawColumnCell和一堆Canvas.TextOut补丁。而 EhLib 11.0.21 的TEhDBGrid一上手就默认支持带图标状态列、鼠标悬停行高亮、CtrlClick 多列排序、右键弹出列配置菜单且所有行为不依赖第三方 DLL 或运行时注入。它不是封装层而是直接重写了 VCL 数据绑定管道中TDataSet到TControl的映射逻辑把TField的DisplayFormat、EditMask、OnGetText等钩子全部接管进自己的TEhDataLink实现里。这意味着你在 Delphi 12.3 中用TEhDBGrid绑定TFDQuery时日期字段自动按ShortDateFormat渲染、数值字段小数位实时响应DisplayFormat变更、Null 值统一显示为[空]而非空白格——这些都不是样式设置是数据通道级的语义透传。适合正在将老旧 BDE/ADO 项目迁移到 FireDAC Windows 11 高 DPI 环境的团队尤其当你发现TStringGrid在 150% 缩放下文字模糊、TDBCtrlGrid无法嵌套TEdit子控件时EhLib 是目前唯一提供完整DPIAwareTrue兼容且源码完全开放的方案。2. EhLib 11.0.21 的安装与 Delphi 12.3 兼容性验证从 .dpk 编译到 IDE 集成的四步闭环EhLib 11.0.21 并非即插即用的.bpl插件其核心价值恰恰在于可编译、可调试、可定制。Delphi 12.3 的 RTL 已移除部分旧版Classes.pas符号如TList.Sort的Compare参数签名变更直接安装旧版.dpk会报E2003 Undeclared identifier: Compare错误。必须先完成源码级适配再走标准组件注册流程。2.1 源码补丁修复 Delphi 12.3 RTL 兼容性断点进入解压后的EhLib\Source目录定位EhLib.pas文件。在TEhDataLink.Sort方法中原代码使用TList.Sort(Compare)形式需替换为TList.Sort(TComparerTObject.Construct(Compare))。具体修改如下// 原始代码Delphi 10.4 及之前 FList.Sort(Compare); // Delphi 12.3 适配后代码 FList.Sort(TComparerTObject.Construct( function(const Left, Right: TObject): Integer begin Result : Compare(Left, Right); end ));提示此修改仅影响TEhDataLink内部排序逻辑不影响外部调用接口。Compare函数签名未变因此所有继承TEhDataLink的控件如TEhDBGrid无需额外修改。同理在EhLib\Source\EhLibDB.pas中搜索TStringList.Sort调用将其替换为TStringList.Sort(TComparerstring.Default)。该补丁确保 EhLib 所有集合类在 Delphi 12.3 的泛型比较器框架下正确运行。2.2 .dpk 编译生成 D12 版本的运行时与设计时包EhLib 11.0.21 提供多个.dpk文件关键路径如下EhLibD12.dpkDelphi 12.3 运行时包含EhLib.pas,EhLibDB.pas等核心单元EhLibDsgnD12.dpk设计时包含EhLibDsgn.pas注册组件到 IDE 工具栏打开 Delphi 12.3 IDE →File → Open→ 选择EhLibD12.dpk→ 右键点击包名 →Compile。若编译通过再打开EhLibDsgnD12.dpk→ 同样执行Compile→Install。此时 IDE 底部状态栏应显示Package EhLibDsgnD12 installed successfully。注意若Install失败并提示Cannot find unit EhLib说明EhLibD12.dpk未成功编译或未加入Search Path。需确认EhLibD12.dpk的Contains列表中已包含EhLib.pas且Options → Directories/Conditionals → Search Path中添加了EhLib\Source路径。2.3 IDE 集成验证检查组件面板与对象查看器可用性安装成功后重启 Delphi 12.3。新建一个 VCL Forms Application → 切换到Tool Palette→ 查找EhLib页签。应可见以下核心组件TEhDBGrid增强型数据网格TEhGroupBox支持折叠/展开的分组框TEhPanel支持圆角、渐变背景的面板TEhButton带图标、悬停效果的按钮在窗体上拖入TEhDBGrid→ 选中控件 → 查看Object Inspector→ 展开EhLib分类 → 检查是否存在OptionsEh、HeaderButtons、FooterButtons等特有属性。若这些属性可编辑且无灰色禁用状态证明设计时集成完成。2.4 运行时兼容性测试用 FireDAC 连接 SQLite 验证中文显示与空值处理创建最小验证工程放置TFDConnection、TFDQuery、TDataSource、TEhDBGridTFDConnection.Params设置DriverIDSQLite;Database.\test.dbTFDQuery.SQL.Text : SELECT 张三 AS name, NULL AS age, 123.45 AS salary FROM dual;TDataSource.DataSet : FFDQuery; TEhDBGrid.DataSource : DataSource1;运行程序观察TEhDBGrid第二行age列是否显示[空]而非空白、salary列是否显示123.45而非科学计数法、name列中文是否清晰无锯齿。若全部符合则 Delphi 12.3 EhLib 11.0.21 FireDAC SQLite 的基础链路已打通。测试项预期结果失败原因定位点组件面板无 EhLib 页签未执行EhLibDsgnD12.dpkInstall检查Tools → Options → Environment Options → Delphi Options → Library → Library Path是否包含EhLib\DesignTEhDBGrid属性不可见EhLibD12.dpk未编译成功查看Messages窗口是否有E2003类错误SQLite 中文显示为乱码TFDConnection.Params缺少CharSetUTF8在Params中添加CharSetUTF8并调用Connected : TrueNULL值列显示为空白格TEhDBGrid.OptionsEh中eoShowNulls未启用将OptionsEh的eoShowNulls设为True3. TEhDBGrid 深度配置从列样式控制到子控件间距的像素级干预TEhDBGrid的强大不在于功能堆砌而在于每一处 UI 行为都暴露了可编程入口。当标准TDBGrid无法满足「销售报表中金额列右对齐、负数红色、小数位动态跟随币种」这类需求时TEhDBGrid提供了三层控制粒度列级格式、单元格级绘制、子控件级布局。3.1 列级格式用TEhDBGridColumn的DisplayFormat与Alignment实现动态数值渲染TEhDBGrid的列对象TEhDBGridColumn继承自TCustomGridCol但扩展了DisplayFormat、EditMask、Alignment等属性。以金额列为例// 假设 Grid1 已绑定数据集第 2 列为 salary 字段 with Grid1.Columns[2] do begin Alignment : taRightJustify; // 文字右对齐 DisplayFormat : #,##0.00; // 千分位两位小数 // 关键动态绑定 CurrencySymbol OnGetCellText : procedure(Sender: TCustomGrid; ACol, ARow: Integer; var AText: string) begin if (ARow 0) and (Sender.DataSource.DataSet.FieldByName(currency).AsString CNY) then AText : ¥ AText else if Sender.DataSource.DataSet.FieldByName(currency).AsString USD then AText : $ AText; end; end;逻辑说明OnGetCellText在每次单元格绘制前触发AText是DisplayFormat格式化后的原始字符串。此处根据同行currency字段值动态拼接货币符号避免在 SQL 中硬编码。Alignment属性直接影响Canvas.TextOut的 X 坐标计算无需手动调整Rect.Left。3.2 单元格级绘制重写OnDrawCell实现负数红色与条件高亮TEhDBGrid的OnDrawCell事件比原生TDBGrid多传入ADrawState: TGridDrawState参数可精确判断当前单元格是否为选中、聚焦、只读等状态procedure TForm1.Grid1DrawCell(Sender: TObject; ACol, ARow: Integer; Rect: TRect; State: TGridDrawState); var Field: TField; Value: Double; begin if (ARow 0) and (ACol 2) then // 仅处理 salary 列索引2 begin Field : Grid1.DataSource.DataSet.Fields[ACol]; if Field is TNumericField then begin Value : Field.AsFloat; if Value 0 then begin Grid1.Canvas.Font.Color : clRed; Grid1.Canvas.Brush.Color : $F0F8FF; // 浅蓝底色 end else begin Grid1.Canvas.Font.Color : clBlack; Grid1.Canvas.Brush.Color : clWindow; end; // 调用父类默认绘制复用 EhLib 的文本居中逻辑 inherited; Exit; end; end; // 其他列走默认绘制 inherited; end;参数说明State是TGridDrawState集合类型包含gdSelected、gdFocused、gdFixed等标志。此处未判断gdSelected是因为TEhDBGrid默认选中行使用独立SelectionColor若需覆盖选中样式需在OnDrawCell开头添加if gdSelected in State then ...分支。3.3 子控件间距通过TEhDBGrid.OptionsEh控制行高、列间隙与标题高度TEhDBGrid的OptionsEh属性是一个TEhGridOptions记录其中eoUseFixedHeight、eoUseFixedWidth控制行列尺寸是否固定。但真正影响「子控件间距」的是RowHeights和TitleHeight// 设置行高为 24 像素默认 18解决高 DPI 下文字拥挤 Grid1.OptionsEh.eoUseFixedHeight : True; Grid1.RowHeights[0] : 24; // 标题行高 Grid1.RowHeights[1] : 24; // 数据行高索引1起为数据行 // 设置列间隙ColumnGap 控制列与列之间的像素距离 Grid1.ColumnGap : 2; // 设置标题高度TitleHeight 影响标题栏整体高度 Grid1.TitleHeight : 26; // 关键启用 eoShowHorzLines 使水平线在行高增加后仍对齐 Grid1.OptionsEh : Grid1.OptionsEh [eoShowHorzLines];提示RowHeights是动态数组RowHeights[0]对应标题行RowHeights[1]对应第一行数据RowHeights[2]对应第二行数据……若数据行数超过Length(RowHeights)TEhDBGrid会自动扩展数组并复制最后一项值。因此生产环境建议初始化SetLength(Grid1.RowHeights, 1000)避免频繁内存分配。4. EhLib 11.0.21 的导出与打印实战绕过 Windows GDI 限制生成高清 PDFDelphi 原生TDBGrid导出 Excel 依赖 OLE 自动化导致 Windows Server 环境下服务崩溃打印预览则受限于TPrinter的 GDI 渲染精度在 200% DPI 下文字发虚。TEhDBGrid内置ExportToExcel和PrintGrid方法但其底层调用TExcelApplication仍有兼容风险。更可靠的方式是利用 EhLib 的TEhGridExport类直接生成二进制 Excel 流再通过TIdHTTP上传至轻量级 PDF 服务。4.1 使用 TEhGridExport 生成 .xlsx 流并保存本地文件TEhGridExport不依赖 Excel 安装直接写入 OOXML 格式uses EhLibExport; procedure TForm1.ExportToXLSX; var Export: TEhGridExport; FileStream: TFileStream; begin Export : TEhGridExport.Create(nil); try Export.Grid : Grid1; // 指向 TEhDBGrid 实例 Export.Options : [eoExportHeaders, eoExportFooter, eoExportHiddenColumns]; // 导出表头、页脚、隐藏列 Export.HeaderFont.Name : Microsoft YaHei; Export.HeaderFont.Size : 10; Export.DataFont.Name : Microsoft YaHei; Export.DataFont.Size : 9; // 生成内存流 Export.ExportToStream; // 保存为文件 FileStream : TFileStream.Create(report.xlsx, fmCreate); try Export.Stream.Position : 0; FileStream.CopyFrom(Export.Stream, Export.Stream.Size); finally FileStream.Free; end; finally Export.Free; end; end;逻辑说明ExportToStream方法将网格内容序列化为IStream接口Export.Stream指向该内存流。CopyFrom直接复制二进制数据避免TStringStream的编码转换损耗。生成的.xlsx在 Excel 2016 和 LibreOffice Calc 中均可正常打开且公式、合并单元格、条件格式均保留。4.2 打印优化用 PrintGrid 的 PageSetup 参数规避 Windows 打印缩放失真TEhDBGrid.PrintGrid方法接受TPrintGridOptions参数其中PageSetup可精确控制纸张方向、边距、缩放procedure TForm1.PrintGridWithScale; var PrintOptions: TPrintGridOptions; begin PrintOptions : []; PrintOptions : PrintOptions [poPrintHeaders, poPrintFooter, poFitToPage]; // 关键设置 PageSetup 强制 100% 缩放禁用 Windows 自动 DPI 缩放 with Grid1.PrintGridOptions.PageSetup do begin PaperSize : psA4; Orientation : poPortrait; TopMargin : 1000; // 单位twips1 inch 1440 twips BottomMargin : 1000; LeftMargin : 1000; RightMargin : 1000; Scale : 100; // 百分比100原始尺寸 end; Grid1.PrintGrid(PrintOptions); end;参数说明Scale : 100是绕过 Windows 打印子系统 DPI 插值的关键。若设为0默认Windows 会根据打印机 DPI 自动缩放导致 120 DPI 打印机输出模糊设为100则强制使用网格原始像素尺寸由打印机固件完成最终渲染保证文字锐利度。TopMargin等单位为twips1 twip 1/1440 inch因此1000≈ 0.7 inch符合国内常用打印边距。4.3 高清 PDF 生成技巧将 TEhDBGrid 截图为 PNG 后调用 wkhtmltopdf当需要生成带公司 Logo、页眉页脚的正式 PDF 报表时TEhDBGrid的DrawTo方法可将网格渲染为TBitmapfunction TForm1.GridToPNG: string; var Bitmap: TBitmap; TempFile: string; begin TempFile : GetTempFileName(GetTempPath, EhGrid, .png); Bitmap : TBitmap.Create; try Bitmap.SetSize(Grid1.Width, Grid1.Height); // 注意此处需确保 Grid1.VisibleTrue Grid1.DrawTo(Bitmap.Canvas.Handle, 0, 0); Bitmap.SaveToFile(TempFile); Result : TempFile; finally Bitmap.Free; end; end; // 调用 wkhtmltopdf 命令行需提前安装 procedure TForm1.GeneratePDF; var PNGFile, PDFFile: string; Cmd: string; begin PNGFile : GridToPNG; PDFFile : ChangeFileExt(PNGFile, .pdf); Cmd : Format(wkhtmltopdf --page-size A4 --margin-top 20 --margin-bottom 20 %s %s, [PNGFile, PDFFile]); WinExec(PAnsiChar(UTF8Encode(Cmd)), SW_HIDE); end;提示Grid1.DrawTo要求控件已渲染到屏幕因此需确保Grid1.Visible : True且窗体已显示。若在服务端无界面环境使用可改用TEhDBGrid.PaintTo方法配合离屏TBitmap但需手动处理滚动条位置和虚拟列偏移。本文还有配套的精品资源点击获取
返回列表