资讯动态

TMS Component Pack 8.3.4.0 全源码组件包:从D7到XE10.3的编译与定制

发布时间:2026/10/16 15:03:43 来源:尧图企业网站定制
简介Delphi 桌面开发中经典的 TMS Component Pack v8.3.4.0 完整源码包面向需要深度定制控件或维护旧项目的 Delphi 开发者覆盖 D7 至 XE10.3并针对 XE10.3 做了兼容性修复解决原版不支持新版环境的问题适用于界面开发、报表、图表、网格等常见业务场景涵盖网格、图表、编辑器、对话框、网络与数据库等众多组件。包内共 2000 个文件压缩后约 166MB以 pas 源文件、dcu 编译单元、hpp 头文件、dfm 窗体定义和 dpr 工程文件为主另有大量 res、bmp、png 等资源、示例程序以及 dpk 安装脚本、inc 配置和演示数据库可直接整体编译、调试并进行二次开发。目前已有 698 人学习下载资源作者实测可用。读者可获得全部控件源码、多版本工程配置以及修改后的 XE10.3 适配细节既能查看底层实现用于学习和改造也能快速迁移旧项目到更高版本无论个人开发者还是企业团队都适合作为中高级 Delphi 开发者的参考。1. TMS Component Pack 是什么、能省多少事从 D7 老项目到 XE10.3 新界面的同一套源码接手一个从 Delphi 7 时代一路维护到 Delphi XE10.3 的桌面系统你会发现界面组件是最难统一的部分原生 VCL 控件在不同版本之间的行为差异不小第三方控件又往往只支持新版本。TMS Component Pack v8.3.4.0 full source 解决的是这个核心问题——一套带完整源码的组件库从 Delphi 7 一直编译到 XE10.3表格、图表、任务栏进度这类高频界面需求不用再自己手写。它适合两类人一类是还在维护 D7 老项目的工程师另一类是在 XE10.3 下想要表格控件又不想重复造轮子的开发者。full source 意味着出了 BUG、想改行为都有源码可以跟进去看这是它跟普通预编译版组件最本质的差别。2. 装之前先动脑包结构、编译器参数与库路径的一次理清很多人在装这类组件包时踩的第一个坑就是把安装理解成双击 setup 然后点下一步。full source 组件包不是这么工作的——它是把包工程文件、源码、编译产物交到你手上由你和 IDE 一起完成注册。装之前把结构、顺序、路径想清楚后面能少折腾一整天。2.1 确认 IDE 版本与包目录结构先找对应版本的 dpk组件包拿到手里解压后目录里一般按编译器版本分好了子目录目录名可能直接叫 D7、XE10.3也可能是对应的版本代号。第一步不是打开 IDE而是先确认当前 IDE 的版本再去组件目录里找对应的包工程文件。确认方法三条打开 IDE 的 About 对话框看版本号。D7 显示 7.0XE10.3 显示 20.0两个版本差距很大编译出来的 DCU 完全不兼容混用会直接报编译错误。打开组件包目录确认里面有没有对应版本的 dpk 文件。dpk 是 Delphi 的包工程文件包含该包内所有单元列表、依赖包列表和条件编译符号。如果目录下只有 D7 而没有 XE10 对应的子目录说明这份源码包覆盖不了你的 IDE 版本不要硬装。确认编译器位置。dcc32.exe 在 IDE 安装目录的 bin 下XE10.3 还带 dcc64.exe 用来编译 64 位目标D7 只有 32 位编译器。需要在 64 位环境下使用组件时32 位和 64 位要分别编译一遍。版本与目录对应关系可以参考下面这个表版本目录确认点可用编译器编译位宽Delphi 7组件包是否有 D7 子目录dcc32.exe32 位XE10.3组件包是否有对应 10.3 子目录dcc32.exe / dcc64.exe32 / 64 位通用IDE 版本号与包目录能对上bin 目录下编译器存在按需这里还要强调一个顺序问题不要直接双击某个 dpk 然后在 IDE 里点 Compile。组件包内部通常分好几层核心运行期包、功能运行期包、设计期包。直接打开一个 dpk 编译会因为依赖包还没编而报一堆找不到符号的错误。先把包之间的依赖顺序摸清楚再用命令行或批处理按顺序一次编完这是最省事的路径。2.2 命令行批量编译dcc32 参数与 bpl 生成过程常见做法是写一个批处理按依赖顺序调用 dcc32。下面这个例子展示的是某个模拟项目的编译脚本骨架实际使用时把路径换成你自己的解压目录即可dcc32.exe -B -Q -ID:\TMS\Source -UD:\TMS\Source;D:\TMS\Source\D7 -LUrtl;vcl D:\TMS\Packages\D7\TMSRun.dpk逐项拆一下参数-B全量重编译忽略已有 DCU 缓存。改过源码之后必须带上否则编译器可能沿用旧产物。-Q安静模式只输出错误和警告。批量编译时日志会比较长不加这个参数容易刷屏。-IInclude 路径用来搜索 .inc 头文件。组件源码里常用 .inc 存放条件编译开关路径配错会导致某些宏没有被定义。-UUnit 搜索路径分号分隔多个目录。编译器按这个顺序查找 .pas 和 .dcu 文件。-LU链接时引用的运行期包列表rtl;vcl是基础包后续功能包还要继续追加自己的依赖包。最后一个参数是要编译的 dpk 文件路径。编译成功的标志不是命令执行完而是 bpl 文件时间戳更新了。Windows 批处理里可以用 errorlevel 判断dcc32.exe -B -Q %1 if errorlevel 1 echo BUILD_FAILED设计期包的文件名通常以 dcl 开头运行期包不带这个前缀。组件面板上的控件由设计期包注册运行期包只在程序运行时被加载。所以编译顺序必须是先运行期包再设计期包。设计期包先编的话会因为找不到运行期包的符号而失败。2.3 库路径与 DCU 缓存老项目打开不报错的配置顺序编译完成只是把包生成了要让 IDE 和你的项目都能找到这些产物还要配路径。库路径配错了新建项目找不到组件、老项目打开报 Not found这类问题占了组件包相关提问的很大比例。我的配置习惯是两条全局 Library Path 只加 DCU 输出目录保证新建项目能直接用组件。项目级 Search Path 加源码目录这样调试时按 F7 能单步进组件源码。不要把源码目录加到全局路径里。全局路径对所有项目生效加源码目录会让 IDE 在每次启动时扫描并可能全量编译一遍源码拖慢启动速度还容易让不同项目的编译产物互相干扰。路径配置的入口XE10.3 在 Tools Options Delphi Options Library项目级在 Project Options Delphi Compiler Search PathD7 的老版本菜单在 Project Options Directories/Conditionals名称略不同但逻辑一样。手动填路径时有两件事必须注意目录之间用分号分隔路径里尽量不要有中文和空格。老版本 D7 对带空格的路径支持得很差经常出现“明明路径没问题就是编不过”的玄学错误。配完路径之后关掉 IDE 重新打开一次再加载项目否则组件缓存不会刷新。如果开项目时仍提示找不到某个单元先把项目 Search Path 里的路径逐段检查再用排除法确认是路径问题还是 DCU 缓存问题。3. 高频组件实战表格、任务栏进度与源码级调试的具体做法组件包装上之后真正的价值在具体场景里体现。业务系统中用得最多的三类表格、进度反馈、图表。这三类组件的用法都有一套自己的约定用对了体验提升明显用错了反而比原生控件更卡。3.1 表格组件替换原生 StringGrid虚拟模式与三个必调参数在业务系统里表格类界面占了至少一半。原生 TStringGrid 在小数据量下没什么毛病数据量一上来滚动、重绘、排序全都显得笨重。TMS 包里的表格组件比如 TAdvStringGrid 这类提供了虚拟模式组件只处理可见区域的绘制数据通过回调按需提供给组件不用把整个数据集都塞进 Cells 属性。我经手的一个老项目统计台账系统把原生表格换成虚拟模式的组件之后数据从几百行涨到几万行滚动基本不掉帧。最小接入方式是先放一个表格组件到窗体上然后挂一个取数据的回调procedure TFormMain.AdvGridGetCellText(Sender: TObject; ACol, ARow: Integer; var CellText: string); begin // 虚拟模式下不要直接写 Cells数据由回调返回 if ARow FData.Count then CellText : FData[ARow].GetColumnText(ACol) else CellText : ; end;这段代码里ACol 和 ARow 是当前准备绘制的单元格坐标CellText 是你要返回给组件显示的文本。挂接方式有两种在设计期选中组件在事件列表里选 OnGetCellText或者在运行时写AdvGrid1.OnGetCellText : AdvGridGetCellText;。虚拟模式有必调的三个参数不调会出各种诡异问题虚拟模式开关选项里与 Virtual 相关的开关要打开。打开之后 Cells 属性就不可用了必须靠回调返回数据否则会出现递归或闪烁。列宽模式长文本比较多时把自动列宽关掉改成固定列宽或代码里按需设置。自动列宽在滚动时会反复测量文本宽度性能可能比原生控件还差。排序行为默认的点击列头排序在虚拟模式下经常失效因为组件只持有界面行号不掌握真实数据。正确做法是在排序事件里对内存数据源排序然后刷新表格显示。另外补充一点在旧版 Windows 主题环境下建议把组件的双缓冲参数重新确认一次。某些第三方皮肤会和它冲突导致表格重绘闪烁这类问题多半不是组件本身的锅而是渲染层打架。3.2 任务栏进度与图表两个能立刻提升体验的组件桌面程序除了主窗口里的进度条Windows 7 之后还支持在任务栏图标上直接显示进度。老项目里做批量导入时用户切到别的窗口就不知道导入有没有卡死。TMS 包里的任务栏进度组件用法很直接拖到主窗体上在循环里给 Progress 属性赋值TaskProgress1.Show; TaskProgress1.Progress : 0; for I : 0 to FTask.Count - 1 do begin // 这里放真实的业务处理 ProcessOneTask(FTask[I]); TaskProgress1.Progress : (I 1) * 100 div FTask.Count; Application.ProcessMessages; end; TaskProgress1.Hide;这段代码里(I 1) * 100 div FTask.Count 计算的是当前完成进度百分比用整除避免出现小数。注意这个组件依赖任务栏按钮存在如果窗体设置了 ToolWindow 样式或类似的无任务栏按钮扩展样式进度条不会显示这不是组件问题是窗口样式问题。图表场景统计报表离不开柱状图和折线图。图表组件接入数据时批量操作要用 BeginUpdate 和 EndUpdate 包住避免每加一个点就重绘一次ChartView1.BeginUpdate; try ChartView1.Series[0].Clear; for I : 0 to FReport.Count - 1 do ChartView1.Series[0].Add(FReport[I].Value, FReport[I].Name); finally ChartView1.EndUpdate; end;这里 BeginUpdate 让图表组件挂起重绘EndUpdate 再统一刷新。不加这对调用的循环数据一多画面会反复闪烁这是图表组件使用的第一课。3.3 full source 的价值断点进源码把黑匣子拆开full source 版和预编译版最大的区别体现在组件行为与预期不一致的时候。曾有一次我在某数据台账系统里发现表格组件按列排序时中文排序结果不符合预期顺序。如果是预编译版遇到这种问题只能绕过组件排序自己在外面实现一套排序逻辑但 full source 版可以给排序事件打断点单步进入组件源码发现它默认用的是系统区域设置下的字符序比较不是按拼音或 Unicode 码位排。换成指定区域设置的比较函数之后排序行为就正常了。调试步骤分四步走把源码目录加入项目 Debug 模式的 Search Path。这里注意是 Debug 模式Release 模式通常不加载源码路径。在界面回调或组件构造函数里下断点运行到触发点。按 F7 进入组件源码观察它调用的比较函数和内部状态。用 Watch 窗口关注条件编译分支下的局部变量确认当前代码走到了哪条分支。组件源码里的条件编译非常多同一个方法在不同 Delphi 版本下编译出来的代码可能差异很大。看不出来走的是哪个分支时我习惯在怀疑的位置临时加一行 OutputDebugString把关键变量打出来再看日志这比在 Watch 窗口里猜变量名快得多。4. 改源码做私有定制从 dpk 追踪到条件编译的一整套流程full source 版最吸引人的地方是可以改源码但改源码有一套纪律。没有纪律的乱改会在升级组件版本时变成一场灾难。这一章讲的是怎么改、改完怎么编、以及如何让改动在将来还能被维护。4.1 先从 dpk 定位单元再打开源码改行为改动之前先打开 dpk 文件找到你要修改的单元属于哪个包。dpk 的 contains 段列出了包内所有单元单元被哪些包引用也可以从这里看出来。千万不要直接全局搜索某个单元然后开改——它可能同时被多个包引用你只重编其中一个包其他包还在用旧二进制运行时会出现类结构不一致的崩溃。以调整表格组件默认行高为例。找到对应单元后在构造函数里加一段受宏控制的代码constructor TAdvGrid.Create(AOwner: TComponent); begin inherited Create(AOwner); {$IFDEF TEAM_DEFAULT_ROW_HEIGHT} DefaultRowHeight : 26; // 中文字体下 24 以下容易裁切 {$ENDIF} end;同步在公共宏头文件里定义这个开关{$DEFINE TEAM_DEFAULT_ROW_HEIGHT}这里的关键是所有私有改动都用 TEAM 开头的前缀宏包裹而不是直接写死在代码里。这样做的原因有两个。一是将来升级源码时搜索 TEAM_ 前缀就能快速定位所有自己改过的地方二是其他项目如果不希望使用这个默认行高不定义这个宏就能保持原样互不影响。4.2 条件编译的粒度分版本改和分功能改组件源码内部已经有大量按 Delphi 版本划分的宏比如区分 D7 与 XE10.3 的代码分支。自己加宏时建议用团队前缀避开官方宏并且把版本分支写在自己宏的最外层{$IFDEF TEAM_FIX_SORTING} // 自定义排序修复 {$IFDEF DELPHI10_3} // 只在 10.3 下需要额外处理 {$ENDIF} {$ENDIF}这样将来打开源码搜索 TEAM_ 前缀能一眼看到所有私有改动区。升级组件版本时把官方新版本源码和当前工作区做差异比对窗口里只显示你改过的几个区域合并成本会低很多。如果不加宏直接改源码升级时会很痛苦等于在几千行官方代码里找出自己动过的逻辑。这里有一个很常见的错误做法就是往源码里写绝对路径比如{$I C:\MyPath\Config.inc}。这种写法在当前机器上能编过换一台机器编译就失败。应该用相对路径或者把 .inc 文件的目录加到项目选项的 Include 搜索路径里。4.3 重编译顺序与输出验证先编依赖包再编引用包组件包的编译顺序由依赖关系决定通常分三层核心运行期包、功能运行期包、设计期包。第一层有任何改动都必须从第一层开始全量重编。只重新编译设计期包改动不会真正生效因为功能包和核心包里还是旧代码。一个按依赖顺序编译的示例dcc32.exe -B -Q -UD:\TMS\Source -LUrtl;vcl D:\TMS\Packages\Core\TMSRun.dpk dcc32.exe -B -Q -UD:\TMS\Source;D:\TMS\Packages\Core -LUrtl;vcl;TMSRun D:\TMS\Packages\Grid\TMSGrid.dpk dcc32.exe -B -Q -UD:\TMS\Source;D:\TMS\Packages\Grid -LUrtl;vcl;TMSRun;TMSGrid D:\TMS\Packages\Design\dclTMSFull.dpk三条命令的含义分别是第一条编译核心包第二条编译表格功能包并链接核心包第三条编译设计期包并链接所有运行期包。-LU参数里的包名顺序就是链接顺序后面的包可以引用前面的包。编译完成后检查每个 bpl 文件的时间戳。三个 bpl 的修改时间都应该是刚才的编译时间哪个没更新就说明哪个包被跳过或编译失败。再去看错误日志定位到具体单元优先怀疑条件编译分支——看看当前编译命令定义的条件符号是否覆盖了你期望的分支。最后强调一条改完源码后必须让 IDE 里的旧 DCU 失效。最稳妥的做法是关掉 IDE删除 DCU 输出目录下与组件相关的 .dcu 文件再重新编译。跳过这一步会出现“源码改了但运行行为还是旧的”这种特别难排查的问题。5. 装包用包避坑五个最常见的翻车现场与定位路径这些坑不只在 TMS 组件包上出现几乎所有带设计期包的 Delphi 控件库都一样。按“现象、原因、解决”三步去查定位速度会快很多。5.1 现象一组件面板里找不到 TMS 组件但包明明编译成功了原因只有名字以 dcl 开头的设计期包会向 IDE 注册组件。只编译运行期包组件面板不会出现任何新控件还有一种情况是包已经编译但没在 Install Packages 列表中勾选启用。解决打开 IDE 的 Component Install Packages点击 Add 选择编译好的 dcl 开头 bpl勾选确认后组件面板就会出现。添加后如果面板仍不刷新重启 IDE 再看一次。5.2 现象二编译报错提示某个 TMS 单元被不同版本的编译器编译过原因DCU 文件带有编译器版本指纹。D7 编出来的 DCU 拿到 XE10.3 下用编译器会直接拒绝加载。这类报错通常出现在项目引用了旧 DCU 目录或全局库路径里混着多个版本的产物。解决清理库路径只保留当前 IDE 版本对应的目录然后重新编译组件包生成匹配当前编译器的 DCU。不要想着跨版本复用 DCU每个 Delphi 大版本都要有自己的 DCU 输出目录这条路没有后悔药。5.3 现象三XE10.3 下调用组件方法报 E2010 Incompatible types原因XE 之后 string 默认为 UnicodeString老组件内部部分函数签名用的是 AnsiString。项目里还留着 D7 时代的 AnsiString 局部变量时一传参就会类型不兼容。解决把调用处的变量类型改为 string。如果必须与老数据格式兼容用显式转换再传参。共享源码的情况下用条件编译把两个版本的差异隔开{$IFDEF UNICODE} S : UnicodeStr; {$ELSE} S : AnsiStr; {$ENDIF}5.4 现象四打开老窗体文件时提示 Class TXXX not found原因DFM 文件里记录的是组件类名窗体创建时需要找到注册的类。项目没有勾选对应的运行时包也没有把组件单元引入项目类就没有注册打开窗体就会失败。解决在 Project Options 里勾选需要的运行时包让 bpl 在运行时被加载或者在项目代码里用 RegisterClass 手动注册组件类前提是组件单元已通过 uses 引入。如果存在多个版本的包同时被加载注意同名类冲突把不需要的旧包卸载掉。5.5 现象五改了源码重新编译运行时组件行为还是老样子原因最常被忽略的是 DCU 缓存旧文件没有清除或者旧的 bpl 被其他进程占用无法覆盖。IDE 实际加载的仍是编译前的旧代码。解决关掉 IDE删除组件目录下所有旧 .dcu 与 .bpl包括输出目录和系统库路径下的同名文件重新用 -B 参数全量编译三个层级的包。如果项目同时安装了多个组件包检查运行时包列表里是否残留了旧条目残留的要删掉。6. 进阶把组件源码放进版本控制建立团队私有分支6.1 用 git 管理组件源码升级组件版本时才不慌full source 组件和普通项目代码一样必须纳入版本控制。我的习惯是把组件源码单独放一个 git 仓库分支分两类vendor 分支存放官方原始代码每次拿到新版本就切到 vendor 分支提交一次team 分支放团队的私有改动。这样升级版本时能清楚看到官方代码改了什么、自己改了什么合并冲突的范围也可控。初始化的命令很简单git checkout -b vendor/tms-8.3.4.0 git add -A . git commit -m vendor: TMS Component Pack 8.3.4.0 full source git checkout -b team/tms-fixes后续所有利用 4.1 和 4.2 的 TEAM_ 宏做的改动都提交到 team/tms-fixes 分支。升级组件版本时先更新 vendor 分支再切回 team 分支做 rebasegit checkout vendor/tms-8.3.4.0 git pull origin vendor/tms-8.3.4.0 git checkout team/tms-fixes git rebase vendor/tms-8.3.4.0如果团队里不止一个人rebase 之后强制推送要谨慎建议改成分支合并避免重写已经共享的历史。我在这上面交过学费早期改组件源码时不带版本标记后来官方出更新补丁一合并就冲突面对几百个源文件根本分不清哪些改动是官方新加的、哪些是自己的老改动。后来把“所有私有改动必须带 TEAM_ 宏且进 git”当成规矩改动注释里写清“为什么改”升级组件版本从解压到重新编译一般一个小时以内能收工。希望帮到你。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑