多彩编程 多彩编程MZPH · CODE BLOG
ARTICLE DETAIL

文章详情

深耕前端与后端开发技术的一线实战笔记与踩坑复盘。

TMS VCL UI Pack v13.5.11.0 完整源码版:Delphi 7-13 与 C++Builder 安装、调优与避坑指南

TMS VCL UI Pack v13.5.11.0 完整源码版:Delphi 7-13 与 C++Builder 安装、调优与避坑指南 简介TMS VCL UI Pack v13.5.11.0 完整源码版面向 Delphi 与 CBuilder 7 至 13 Florence 的桌面开发者尤其适合需要快速构建专业级 Windows 界面、又不愿从零造轮子的中高级程序员。官方 2025 年 12 月发布600 余个控件全部开放源码可直接编译进项目并按需二次修改。压缩包共约 2000 个文件、105.24MB以 pas 源码、dfm 窗体、dproj/dpr 工程、res/dcr 资源与 ico/jpg 图标素材为主另含 pdf 文档、csv 数据与 50 多个可直接运行的 Demo覆盖 Excel 导入、Planner 排程、Outlook 导航与高 DPI 报表等场景。本次更新为 TAdvStringGrid 加入 ButtonRect 单元格类型可在表格内嵌按钮并响应点击TAdvListView 支持 OnHint 多行悬停提示同时优化高 DPI 缩放修复 Ribbon 折叠动画与 Office 2021 样式在 150% 以上缩放下的错位。解压后运行 recompile.exe 即可一键编译 VCL 包IDE 面板会新增专属页签拖放即用。目前已有 123 人学习下载。1. TMS VCL UI Pack v13.5.11.0Delphi 与 CB 7-13 的完整源码版到底解决什么问题如果你正在维护一套 Delphi 或 CBuilder 的老项目界面还停留在 TStringGrid 加 TPanel 拼出来的年代那你大概率听过 TMS VCL UI Pack 这个名字。v13.5.11.0 这个版本号背后是一套覆盖 Delphi 7 一直到 Delphi 13 Florence 以及对应 CBuilder 版本的完整源码组件包。注意关键词是「完整源码版」——不是只有编译好的 bpl 和 dcu而是能直接编译进 IDE、能单步调试、能改一行重新构建的源码。这解决的核心痛点是当官方组件行为不符合你的业务逻辑时你不需要等厂商发补丁自己就能动手改。适合谁适合那些项目周期长、UI 要求高、又不想被第三方闭源组件锁死的 Delphi/CB 团队。热搜里常出现「delphi最新」「delphi 13 community edition」这类词说明很多人正在评估升级路径而这个包恰好是升级过程中绕不开的一环。2. 源码版安装与 Delphi/CB 版本适配从解压到第一个 TAdvStringGrid2.1 为什么源码版比二进制版更值得折腾二进制版安装快双击 bpl 就完事但一旦遇到 Delphi 13 Florence 的编译器变更或者 CBuilder 的运行时库差异你就只能干等。源码版虽然安装步骤多几步但换来的是完全可控。TMS VCL UI Pack 的源码结构通常按包分组核心运行时包、设计期包、以及针对不同 Delphi 版本的编译脚本。v13.5.11.0 明确支持 Delphi 7 到 13这意味着同一套源码里存在大量条件编译指令比如{$IFDEF DELPHI13}或{$IF CompilerVersion 35}。你不需要手动改这些但得知道它们的存在否则编译报错时你会一头雾水。安装前先确认你的 IDE 版本和对应的包目录。常见做法是解压后找到packages文件夹里面会有类似Delphi13、Delphi12、CB13这样的子目录。每个子目录里有一个.groupproj文件用 IDE 打开它然后 Build All。注意不要直接 Install 设计期包先 Build 运行时包再 Build 设计期包最后 Install。顺序错了会出现「找不到 DCU」的玄学错误。2.2 用命令行批量编译所有包一个可复现的 bash 脚本如果你有多个 Delphi 版本需要同时维护手动开 IDE 编译太慢。可以用命令行编译器dcc32.exe或dcc64.exe批量处理。下面这个脚本假设你把 TMS 源码解压到了D:\Components\TMSVCLUIPack并且 Delphi 13 安装在默认路径。#!/bin/bash # 批量编译 TMS VCL UI Pack 源码包以 Delphi 13 为例 # 注意路径中的空格需要引号包裹否则 dcc32 会解析失败 TMS_ROOTD:/Components/TMSVCLUIPack DELPHI_BINC:/Program Files (x86)/Embarcadero/Studio/37.0/bin DCC$DELPHI_BIN/dcc32.exe # 先编译运行时包 cd $TMS_ROOT/packages/Delphi13 for pkg in *.dpk; do echo 正在编译: $pkg $DCC -B -Q -W -H -N$TMS_ROOT/source $pkg if [ $? -ne 0 ]; then echo 编译失败: $pkg请检查源码路径和搜索路径 exit 1 fi done # 再编译设计期包 cd $TMS_ROOT/packages/Delphi13 for pkg in *Design*.dpk; do echo 正在编译设计期包: $pkg $DCC -B -Q -W -H -N$TMS_ROOT/source $pkg done逻辑说明-B强制重新编译所有单元避免旧 DCU 干扰-Q静默模式减少输出-W输出警告-H生成头文件CBuilder 需要-N指定源码搜索路径。参数里最容易翻车的是-N后面的路径如果 TMS 源码分散在多个子目录需要重复写多个-N。另外设计期包的命名通常包含Design或Dcl用通配符匹配时先ls确认一下。2.3 CBuilder 用户的额外步骤头文件与运行时包CBuilder 7 到 13 的兼容性比 Delphi 更麻烦因为 CB 需要.hpp头文件和.lib导入库。TMS 源码包里通常已经包含了预生成的头文件但如果你修改了源码必须重新生成。在 IDE 中打开对应的.cbproj或.groupproj编译时会自动生成。命令行下则需要dcc32加上-H参数或者用bcc32编译。常见坑是CB 的运行时包和 Delphi 的运行时包不能混用必须为 CB 单独编译一套。如果你同时装了 Delphi 和 CB建议把包输出目录分开比如output/Delphi13和output/CB13否则会出现「模块重复加载」的报错。3. 核心组件实战TAdvStringGrid、TAdvEdit 与 TAdvOfficePager 的参数调优3.1 TAdvStringGrid 处理万行数据的三个必调属性TAdvStringGrid 是 TMS 包里用得最多的组件但默认配置下加载一万行数据会卡到怀疑人生。血泪经验是必须关掉AutoSizeCells开启VirtualMode并且把Options里的goRowSizing和goColSizing设为 False。下面是一个最小加载示例。procedure TForm1.LoadLargeData; var i: Integer; begin AdvStringGrid1.BeginUpdate; try AdvStringGrid1.Clear; AdvStringGrid1.RowCount : 10001; // 包含标题行 AdvStringGrid1.ColCount : 8; AdvStringGrid1.FixedRows : 1; AdvStringGrid1.Options : AdvStringGrid1.Options - [goRowSizing, goColSizing, goEditing]; AdvStringGrid1.AutoSizeCells : False; AdvStringGrid1.VirtualMode : True; // 关键只渲染可见区域 for i : 1 to 10000 do begin AdvStringGrid1.Cells[0, i] : IntToStr(i); AdvStringGrid1.Cells[1, i] : Item IntToStr(i); // 其他列赋值... end; finally AdvStringGrid1.EndUpdate; end; end;参数说明VirtualMode是性能分水岭开启后网格只绘制可视行滚动时动态取值。但注意开启虚拟模式后Cells属性在滚动时可能返回空值你需要改用OnGetCellData事件来提供数据。BeginUpdate/EndUpdate必须成对出现否则界面会假死。AutoSizeCells在数据量大时会逐格计算宽度直接关掉。如果还是慢检查是否开启了goRangeSelect或goAlwaysShowEditor这些都会增加重绘开销。3.2 TAdvEdit 的输入掩码与验证比 TMaskEdit 强在哪TAdvEdit 支持正则验证和输入掩码比原生 TMaskEdit 灵活得多。比如你要限制输入为「3 位字母 4 位数字」的工单号可以这样设procedure TForm1.SetupAdvEdit; begin AdvEdit1.EditType : etMask; AdvEdit1.Mask : LLL0000; // L 表示字母0 表示数字 AdvEdit1.MaskType : mtRegEx; AdvEdit1.RegEx : ^[A-Z]{3}\d{4}$; AdvEdit1.ErrorMessage : 格式3位大写字母4位数字例如 ABC1234; AdvEdit1.ValidChars : ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789; end;逻辑说明Mask提供视觉提示RegEx做最终校验。ValidChars限制可输入字符避免用户粘贴非法内容。注意MaskType设为mtRegEx后Mask属性只影响显示实际校验走正则。如果用户输入小写字母ValidChars会直接拦截不会触发正则。常见坑是在OnExit里做校验时如果正则不匹配不要直接SetFocus否则会陷入死循环应该用ErrorProvider或状态栏提示。3.3 TAdvOfficePager 的页面切换动画与内存占用TAdvOfficePager 适合做多标签工作区但每个页面如果都放一个 TAdvStringGrid内存会飙升。建议用「延迟创建」策略只在页面首次激活时创建内容。procedure TForm1.AdvOfficePager1Change(Sender: TObject); var Page: TAdvOfficePage; begin Page : AdvOfficePager1.ActivePage; if Page.ControlCount 0 then begin // 根据页面 Tag 或 Name 动态创建对应控件 if Page.Tag 1 then CreateGridOnPage(Page) else if Page.Tag 2 then CreateChartOnPage(Page); end; end;参数说明ActivePage返回当前页ControlCount 0表示尚未创建。Tag用来标识页面类型。注意动态创建的控件要设置Align : alClient并且 Parent 设为Page。如果页面切换频繁可以在OnChange里加一个Screen.Cursor : crHourGlass避免用户以为卡死。另外TAdvOfficePager 的Animate属性在远程桌面或虚拟机里会导致闪烁建议在那种环境下关掉。4. 避坑与排查源码版安装后最常见的 5 个翻车现场4.1 编译时报「Unit TMSVCLUIPack was compiled with a different version」现象安装设计期包时提示某个 DCU 版本不匹配。原因之前装过二进制版旧的 DCU 残留在 IDE 的库路径里。解决在 IDE 的Tools Options Library中删除所有指向 TMS 旧版本的搜索路径然后重新 Build 源码包。如果还不行搜索整个磁盘的TMS*.dcu全部删掉。4.2 CBuilder 链接时找不到 .obj 文件现象CB 项目链接阶段报Unresolved external TAdvStringGrid::...。原因源码包编译时没有生成 C 的 .obj 或 .lib。解决确保用 CB 的编译器重新编译了所有.cpp对应的包并且在项目选项里勾选Link with runtime packages和Use dynamic RTL。如果用的是静态链接需要把 TMS 的.lib文件加入项目。4.3 Delphi 13 Florence 下设计期包无法注册现象Install 后工具栏看不到 TMS 组件页。原因Delphi 13 的 IDE 对设计期包的签名或路径有更严要求。解决以管理员身份运行 IDE重新打开.groupproj右键设计期包选择Install。如果还是不行检查registry中的Known Packages是否指向了正确的 BPL 路径。常见做法是手动添加 BPL 路径到HKEY_CURRENT_USER\Software\Embarcadero\BDS\37.0\Known Packages。4.4 运行时提示「Class TAdvStringGrid not found」现象程序在客户机上运行时报类未注册。原因运行时包没有随 exe 一起发布或者 exe 编译时用了Runtime packages但客户机缺少对应的 bpl。解决要么把 TMS 的 bpl 复制到 exe 同目录要么在项目选项里取消Build with runtime packages改为静态链接。静态链接的代价是 exe 体积增大但部署简单。4.5 修改源码后重新编译IDE 里组件行为没变现象改了 TAdvEdit 的源码重新 Build 并 Install但设计期拖出来的控件还是旧行为。原因IDE 加载的是旧的 BPL没有真正替换。解决关闭 IDE删除所有 TMS 的 BPL 和 DCU重新打开源码包编译安装。注意Delphi 的 IDE 会缓存 BPL有时候需要重启两次。5. 进阶技巧用条件编译让一套源码同时兼容 Delphi 7 和 Delphi 135.1 条件编译指令的实战写法TMS 源码里大量使用{$IFDEF}来区分版本。如果你想自己加一段兼容代码比如 Delphi 7 没有TBytes类型可以这样写{$IFDEF DELPHI7} type TBytes array of Byte; {$ENDIF} function GetData: TBytes; begin {$IF CompilerVersion 35} // Delphi 13 Result : TFile.ReadAllBytes(data.bin); {$ELSE} // Delphi 7 手动读取 with TFileStream.Create(data.bin, fmOpenRead) do try SetLength(Result, Size); ReadBuffer(Result[0], Size); finally Free; end; {$IFEND} end;逻辑说明CompilerVersion是 Delphi 内置常量Delphi 7 对应 15Delphi 13 对应 35。{$IFEND}是旧版结束标记新版也可以用{$ENDIF}。注意条件编译不能跨函数边界必须写在函数内部或类型声明处。如果一段代码在多个版本间差异很大建议抽成独立单元用不同的.inc文件包含。5.2 用构建脚本自动切换版本维护多版本时手动改条件编译容易漏。可以写一个 Python 脚本根据目标版本生成不同的.inc文件。# generate_inc.py # 根据目标 Delphi 版本生成 tms_config.inc import sys version_map { delphi7: 15, delphi13: 35, cb13: 35, } target sys.argv[1] ver version_map.get(target) if not ver: print(f未知目标: {target}) sys.exit(1) with open(tms_config.inc, w) as f: f.write(f{{$DEFINE TMS_TARGET_VERSION {ver}}}\n) if ver 35: f.write({$DEFINE TMS_HAS_TBYTES}\n) else: f.write({.$DEFINE TMS_HAS_TBYTES}\n) print(f已生成 tms_config.inc目标版本 {target} (CompilerVersion{ver}))然后在源码里{$I tms_config.inc}用TMS_HAS_TBYTES控制代码分支。这样切换版本只需重新运行脚本不用手动改源码。参数说明version_map里的数字是 Delphi 的CompilerVersion常量Delphi 7 是 15Delphi 2007 是 18.5Delphi 13 是 35。CBuilder 的版本号通常和同代 Delphi 一致。5.3 验证方法写一个跨版本的最小测试用例改完兼容代码后怎么确认没问题建一个最简单的 VCL 项目只放一个 TAdvStringGrid 和一个按钮按钮里调用你修改过的函数。分别在 Delphi 7 和 Delphi 13 下编译运行看输出是否一致。如果 Delphi 7 下报「找不到 TBytes」说明条件编译没生效。如果 Delphi 13 下报「重复定义」说明{$IFDEF}写反了。我一般会在项目里加一个BuildAll.bat一键编译所有目标版本省得来回切 IDE。最后说个习惯每次升级 TMS 版本前先把当前能跑的源码包整个备份一份包括你改过的所有文件。因为新版本可能改了接口你的修改不一定能直接合并。这个后悔药我吃过好几次亏才养成。希望帮到你。本文还有配套的精品资源点击获取
返回列表