拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Delphi 13.1 跨平台控件 TMS FNC UI Pack v7.1.1.0 源码实战:VCL 与 FMX 一套代码

Delphi 13.1 跨平台控件 TMS FNC UI Pack v7.1.1.0 源码实战:VCL 与 FMX 一套代码 简介本资源为TMS FNC UI Pack v7.1.1.0完整源码包面向使用Delphi与C Builder进行跨平台界面开发的程序员覆盖XE7至13 Florence版本。控件包提供现代化、触摸友好的UI组件支持Windows、Mac、Linux、iOS与Android多平台适合希望快速构建响应式应用界面的中高级开发者。压缩包共约2000个文件大小31.09MB以pas源码、dproj与dpr工程文件、dfm与fmx窗体、res与ico资源、dcr组件包及html文档为主另含少量csv、svg、png等素材结构完整便于按模块查阅。已有56人学习下载。完整源代码意味着开发者可自由修改与扩展组件配合文档能深入理解实现机制节省界面开发时间将精力集中于业务逻辑与创新功能长期项目亦可获得持续更新支持。1. Delphi 13.1 控件之 TMS FNC UI Pack v7.1.1.0一套源码如何横跨 VCL 与 FMX手里维护着两套界面代码的 Delphi 团队大概都经历过这种拉扯VCL 项目里调好的表格样式搬到 FMX 项目要重写一遍Windows 上跑通的树形控件编译到移动端就散架。TMS FNC UI Pack 就是冲着这个痛点来的——它把 Grid、TreeView、Toolbar、Planner、RichEditor 这类常用控件做成一套跨框架、跨平台的实现同一份业务代码在 VCL、FMX 甚至 Web 端都能编译。标题里的 v7.1.1.0 对应的是支持 Delphi CBuilder XE7 到 13 Florence 的版本Full Source 意味着拿到的是完整源码不是只有编译好的 DCU。这篇文章不聊虚的就讲这套源码包怎么装、怎么在 VCL 和 FMX 里跑通第一个控件、参数怎么调、升级时哪些坑会让人翻车。适合已经在用 Delphi 做桌面或跨平台界面、想减少重复劳动的中高级开发者。2. 先搞清楚 FNC 架构为什么它能一套代码跑 VCL 和 FMX2.1 FNC 的分层设计到底解决了什么问题传统 Delphi 控件要么绑死 VCL要么绑死 FMX根源在于两者底层绘制和消息机制完全不同。VCL 依赖 Windows GDI 和窗口句柄FMX 走的是跨平台渲染抽象层。TMS FNC UI Pack 的做法是在两者之上再抽一层核心逻辑数据模型、布局计算、事件分发写成框架无关的代码绘制和平台交互则通过一层适配器分别对接 VCL 和 FMX。这意味着你写业务逻辑时操作的是TTMSFNCGrid这样的统一类型编译时由条件编译或运行时适配决定底层走哪套。Full Source 的价值就在这里——你能看到适配层怎么写的遇到平台差异时能自己改而不是干等厂商发新版。实际项目里我一般把 FNC 控件当成「逻辑层统一、表现层可替换」的组件用。比如一个数据录入界面Grid 的列定义、校验规则、数据绑定写一遍VCL 版本和 FMX 版本共用同一个单元只在窗体创建时挂不同的父容器。2.2 源码包目录结构与编译顺序拿到 Full Source 的压缩包解压后不要急着打开 IDE 就编译。先看清楚目录组织TMS 的源码包通常按框架和功能分目录混着编译容易出重复单元警告。典型的结构大致是这样TMSFNCUIPack/ Source/ Core/ # 框架无关的核心单元 VCL/ # VCL 适配层 FMX/ # FMX 适配层 Common/ # 公共工具单元 Packages/ Delphi13/ # 对应版本的包工程 Delphi12/ ... Demos/ VCL/ FMX/编译顺序上核心单元必须先于适配层适配层先于包工程。如果你手动往项目里加单元而不是装包顺序错了会报「unit not found」或者类型不匹配。提示装包之前先备份现有的 IDE 库路径TMS 的安装脚本会往全局路径里塞东西出问题好回滚。2.3 在 Delphi 13.1 里安装包并验证安装分两种方式用官方安装程序或者手动编译包工程。Full Source 用户建议走手动方式可控性高。第一步打开对应版本的包工程组。以 Delphi 13 为例进Packages/Delphi13/里面通常有设计期包和运行期包两组。先编译运行期包Runtime再编译设计期包Design顺序反了设计期包找不到运行期单元。第二步编译通过后右键设计期包选 Install。装完在工具面板应该能看到 TMS FNC 的分类页。第三步验证。新建一个 VCL 应用拖一个TTMSFNCGrid到窗体上编译运行。如果报找不到单元检查库路径里有没有把Source/Core、Source/VCL、Source/Common都加进去。// 最小验证代码在窗体 OnCreate 里填几行数据 procedure TForm1.FormCreate(Sender: TObject); begin TMSFNCGrid1.ColumnCount : 3; // 三列 TMSFNCGrid1.RowCount : 5; // 五行 TMSFNCGrid1.Cells[0, 0] : 编号; // 表头 TMSFNCGrid1.Cells[1, 0] : 名称; TMSFNCGrid1.Cells[2, 0] : 数量; TMSFNCGrid1.Cells[0, 1] : 001; TMSFNCGrid1.Cells[1, 1] : 测试项; TMSFNCGrid1.Cells[2, 1] : 10; end;这段代码不涉及任何平台相关调用VCL 和 FMX 下都能跑。ColumnCount和RowCount是行列总数Cells[col, row]是零基索引注意第一个参数是列不是行这点和某些老控件相反容易写反。3. 用 FNC 控件搭一个跨平台数据浏览界面3.1 选 Grid 还是 TreeView数据形态决定控件FNC UI Pack 里控件不少但数据浏览场景最常用的就两个TTMSFNCGrid处理二维表格TTMSFNCTreeView处理层级数据。选型不看哪个高级看你的数据是不是天然分层。如果数据来自数据库的扁平结果集用 Grid绑定直接、排序过滤现成。如果数据有父子关系——比如组织架构、分类目录、BOM 结构——用 TreeView硬塞进 Grid 只会让自己难受。我见过有人把树形数据拍平成 Grid 再用缩进模拟层级维护成本极高加一个节点要改一堆逻辑。这种场景直接上 TreeViewFNC 的 TreeView 支持节点自带数据对象绑定很自然。3.2 数据绑定从数据库到控件的完整链路FNC 控件支持直接绑定TDataSource这是最省事的方式。以 Grid 为例把DataSource属性指向一个TDataSource列会自动根据字段生成也可以手动定义列并指定FieldName。// 假设已有 FDQuery1、DataSource1 指向它 procedure TForm1.SetupGrid; begin // 关闭自动列生成手动控制 TMSFNCGrid1.AutoCreateColumns : False; TMSFNCGrid1.DataSource : DataSource1; // 手动加三列并绑定字段 with TMSFNCGrid1.Columns.Add do begin FieldName : ID; Header : 编号; Width : 80; end; with TMSFNCGrid1.Columns.Add do begin FieldName : Name; Header : 名称; Width : 200; end; with TMSFNCGrid1.Columns.Add do begin FieldName : Qty; Header : 数量; Width : 100; end; end;AutoCreateColumns : False是关键不关掉的话手动列和自动列会打架。FieldName必须和数据集字段名完全一致大小写敏感。Width单位是像素FMX 下会按屏幕缩放自动换算不用手动乘 DPI 系数。TreeView 的绑定稍复杂因为层级关系数据集本身表达不了。常见做法是查两次先查根节点再按父 ID 查子节点递归填充。procedure TForm1.LoadTree(ParentNode: TTMSFNCTreeViewNode; ParentID: Integer); var Node: TTMSFNCTreeViewNode; begin FDQuery2.Close; FDQuery2.ParamByName(pid).AsInteger : ParentID; FDQuery2.Open; while not FDQuery2.Eof do begin if ParentNode nil then Node : TMSFNCTreeView1.AddNode(nil, FDQuery2.FieldByName(Name).AsString) else Node : TMSFNCTreeView1.AddNode(ParentNode, FDQuery2.FieldByName(Name).AsString); Node.Data : Pointer(FDQuery2.FieldByName(ID).AsInteger); // 存 ID 备用 LoadTree(Node, FDQuery2.FieldByName(ID).AsInteger); // 递归子节点 FDQuery2.Next; end; end;AddNode第一个参数传 nil 就是根节点传父节点就是子节点。Node.Data是 Pointer 类型存整数 ID 要强制转换取的时候再转回来。递归深度受数据集嵌套层数限制数据量大的话建议改成懒加载展开节点时再查子级。3.3 样式与主题让 VCL 和 FMX 看起来一致FNC 控件自带样式系统不依赖 VCL 主题或 FMX 样式书。这意味着你可以让两个平台的界面长得一样这对需要统一品牌形象的产品很重要。样式通过TMSFNCGrid1.Appearance系列属性控制或者加载.fnc样式文件。常用参数属性作用典型值Appearance.FixedColor表头背景色$00E0E0E0Appearance.FixedFont.Color表头文字色clBlackAppearance.NormalColor数据区背景clWhiteAppearance.SelectedColor选中行背景$00CCE8FFAppearance.GridLinesColor网格线颜色$00C0C0C0颜色值用 Delphi 的TColor格式注意是 BGR 不是 RGB$00CCE8FF实际是浅蓝。改完样式记得调Invalidate或Repaint刷新某些属性不会自动触发重绘。注意FMX 下部分样式属性名和 VCL 略有差异Full Source 里能看到适配层怎么映射的遇到属性不生效先去源码里确认该平台是否支持。4. 避坑与排查升级和跨平台编译的五个血泪教训4.1 从旧版升级后控件消失或报类未注册现象装完新版包打开旧项目设计器里控件变成灰块或者编译报「Class TTMSFNCGrid not found」。原因旧版 DCU 还在库路径里和新版单元冲突或者设计期包没重新安装IDE 加载的还是旧包。解决先卸载旧包清掉库路径里所有 TMS 相关条目再装新版。项目里的.dproj可能还引用旧版包名手动检查DCC_UsePackage列表把旧版本号删掉。4.2 FMX 下编译通过但运行时控件不显示现象VCL 版本正常切到 FMX 编译无报错运行后窗体上控件区域一片空白。原因FMX 的父容器和 VCL 不同FNC 控件需要正确的 Parent 设置和 Align。常见是拖到窗体上但 Align 没设控件尺寸为零。解决确认Align设为Client或手动设Width/Height。另外 FMX 下如果父容器是TLayout要确保 Layout 本身有尺寸。Full Source 里 FMX 适配层的Paint方法能看到绘制条件尺寸为零直接跳过绘制。4.3 中文显示乱码或字体发虚现象Grid 里中文变成问号或者 FMX 下文字边缘模糊。原因VCL 下默认字体不支持中文FMX 下字体渲染受Quality属性影响。解决VCL 把Font.Name设为「微软雅黑」或「宋体」Font.Charset设为GB2312_CHARSET。FMX 下设Font.Family为中文字体并把Quality调到High或ClearType。注意 FMX 移动端字体名和桌面不同Android 用「sans-serif」iOS 用「PingFang SC」。4.4 大数据量下滚动卡顿现象几千行数据滚动时明显掉帧VCL 下尤其明显。原因默认开启了全部重绘每次滚动重画所有可见和不可见单元格。解决开启虚拟模式。Grid 的VirtualCells相关属性打开只渲染可见区域。数据源用分页查询别一次性拉十万行。Full Source 里能看到绘制循环确认是否走了虚拟路径。4.5 CBuilder 下链接报重复符号现象Delphi 项目正常CBuilder 编译报「Duplicate symbol」或「Unresolved external」。原因C 和 Delphi 的单元命名空间处理不同某些 FNC 单元在 C 下需要额外的#pragma link或命名空间限定。解决检查包工程的 C 输出设置确保.hpp文件生成正确。Full Source 里带.hpp的单元直接用没带的可能需要手动加extern C声明。这类问题在 TMS 论坛有专门帖子搜单元名加 CBuilder 基本能找到答案。5. 进阶用 Full Source 定制控件行为与版本迁移策略拿到 Full Source 最大的好处不是省授权费是能在源码层面改行为。举个实际例子项目要求 Grid 的某列在编辑时只能输入特定格式内置的编辑器不满足直接改源码比继承重写快。找到Source/Core下 Grid 编辑器的单元定位到DoEditKeyPress或类似的按键处理方法在里面加校验逻辑。改完重新编译运行期包设计期包会自动引用新 DCU。这种改法要注意版本升级时合并——把改动记在单独的补丁文件里升级后重新应用别直接覆盖新版源码。版本迁移上从 XE7 到 13 Florence 跨度很大FNC 的 API 基本保持兼容但底层依赖的 RTL 有变化。迁移时重点检查三处字符串类型string在移动端是UnicodeString、泛型容器用法、以及平台条件编译符号。Full Source 里每个版本的条件编译分支都保留着对照着看能快速定位不兼容点。我自己的习惯是每升级一次 Delphi 大版本先拿 FNC 的 Demo 工程编译一遍Demo 全过再动正式项目。Demo 里覆盖了大部分控件用法能提前暴露适配问题。另外把对源码的修改集中在一个patches目录用脚本在每次升级后自动打补丁比手动改可靠得多。这套流程跑了几个大版本没再出现过升级后界面集体翻车的情况。希望帮到你。本文还有配套的精品资源点击获取
返回列表