ARTICLE DETAIL

资讯详情

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

Delphi 12.3 跨框架 UI 开发:TMS FNC UI Pack v6.2.0.0 实战指南

Delphi 12.3 跨框架 UI 开发:TMS FNC UI Pack v6.2.0.0 实战指南 简介本资源为面向 Delphi 12.3 开发者的 TMS FNC UI Pack v6.2.0.0 控件包适合使用 FireMonkey 与 VCL 框架进行跨平台界面开发的中高级程序员用于快速构建现代化、多平台的桌面与移动应用界面。压缩包共约 2000 个文件整体 29.85MB以 556 个 pas 源码单元、157 个 dpr 工程文件、87 个 dfm 窗体、67 个 fmx 跨平台窗体及 37 个 lfm 与 lpr 工程文件为核心辅以 180 个 res 资源、158 个 ico 图标、220 个 jpg 与 27 个 svg 图像素材并包含 8 个 dpk 组件包、5 个 groupproj 项目组及 csv、html、xml 等示例数据便于直接编译与二次开发。已有 55 人学习下载。该控件包提供丰富的 UI 组件与主题样式读者可获取完整源码、示例工程与资源文件用于学习 FNC 跨平台控件架构、界面定制与项目集成提升 Delphi 应用开发效率。1. Delphi 12.3 下 TMS FNC UI Pack v6.2.0.0 到底解决什么问题如果你正在用 Delphi 12.3 做桌面项目又不想把 VCL、FMX、Web 三套 UI 各写一遍TMS FNC UI Pack 就是冲这个痛点来的。它是一套跨框架的 FNCFramework Neutral Component控件库同一批控件源码能同时编译进 VCL、FMX、LCL 甚至 Web 项目v6.2.0.0 这个版本号对应的是 12.3 Athens 的编译环境。很多人搜「Delphi 12.3 控件」时真正想问的是装完之后 Grid、TreeView、Ribbon、Planner 这些控件能不能直接拖上窗体、中文字体会不会糊、数据库绑定要不要额外写代码。这篇不聊虚的就按我实际在 12.3 上装包、建工程、绑数据、调样式的顺序走一遍把能抄的步骤和会翻车的地方都摆出来。适合已经会写 Delphi 基础代码、准备给现有项目换一套现代 UI 的从业者新手照着命令也能跑通最小示例。2. 装包与工程接入从 rar 到能拖控件2.1 先确认你的 Delphi 12.3 是哪种编译目标TMS FNC UI Pack 的安装包解压后不是单一 dpk而是按框架分目录。VCL 走packages\Delphi 12.3\VCLFMX 走packages\Delphi 12.3\FMX两边都要单独编译安装。我一般先确认 IDE 的编译目标菜单 Tools → Options → IDE → Compiling看当前是 Win32 还是 Win64。FNC 控件在 Win32 下最稳Win64 也能用但部分依赖 GDI 的渲染在 Win64 下需要额外确认TMSFNCGraphics单元是否被正确引用。安装顺序建议是先装 Core再装 UI Pack。Core 提供TMSFNCGraphics、TMSFNCUtils这些底层单元UI Pack 的 Grid、TreeView 都依赖它。如果跳过 Core 直接装 UI Pack编译时会报找不到TMSFNCGraphics.TMSFNCGraphics之类的错误这是最常见的翻车点。2.2 用命令行编译安装包避免 IDE 里点半天在 IDE 里逐个右键 Install 也能装但版本一多容易漏。我习惯用命令行先把包编一遍确认没有路径问题cd C:\Program Files (x86)\Embarcadero\Studio\23.0\bin # 先编译 FNC Core dcc32.exe -B -Q D:\TMS\FNC\Core\packages\Delphi 12.3\TMSFNCCoreVCL.dpk # 再编译 UI Pack 的 VCL 包 dcc32.exe -B -Q D:\TMS\FNC\UI Pack\packages\Delphi 12.3\VCL\TMSFNCUIPackVCL.dpk-B是强制全量编译-Q是安静模式只输出错误。路径里的23.0对应 Delphi 12.3 的 Studio 版本号如果你装的是 12.3 的某个补丁版这个数字可能不同去bin目录下看dcc32.exe所在位置即可。编译通过后再回 IDE 里 Install能省掉「明明装了却找不到控件」的玄学问题。2.3 把控件真正拖上窗体一个最小 Grid 示例装完之后在 Tool Palette 里搜TMSFNC应该能看到TMSFNCGrid、TMSFNCTreeView、TMSFNCRibbon等。拖一个TMSFNCGrid到 VCL 窗体上默认是空的。下面这段代码演示怎么在运行时建列、填数据、绑一个TClientDataSetuses TMSFNCGrid, TMSFNCGridData, Data.DB, Datasnap.DBClient; procedure TForm1.FormCreate(Sender: TObject); var Col: TTMSFNCGridColumn; begin // 建三列 Col : TMSFNCGrid1.AddColumn; Col.HeaderText : 编号; Col.Width : 80; Col : TMSFNCGrid1.AddColumn; Col.HeaderText : 名称; Col.Width : 200; Col : TMSFNCGrid1.AddColumn; Col.HeaderText : 金额; Col.Width : 120; Col.Alignment : taRightJustify; // 绑数据源 TMSFNCGrid1.DataSource : ClientDataSet1; TMSFNCGrid1.AutoSizeColumns; end;AddColumn返回的是TTMSFNCGridColumnHeaderText是表头Alignment控制对齐。DataSource一绑Grid 会自动按字段顺序映射列但前提是列的FieldName要设对否则显示空白。AutoSizeColumns在数据量大时会卡建议只在初始化时调一次别放在AfterScroll里。提示FNC 控件的DataSource属性在 VCL 和 FMX 下行为一致但 FMX 下TClientDataSet需要额外引用Datasnap.DBClient单元否则编译报错。3. 数据库绑定与 TreeView 联动把热搜里的「delphi通过数据库实现treeview」落地3.1 为什么 FNC TreeView 绑数据比原生 TreeView 省事原生TTreeView绑数据库要自己写递归、自己管Node.Data字段一多就乱。FNC 的TMSFNCTreeView支持DataSource直接绑配合ParentField和KeyField两个属性就能自动建层级。我一般用TClientDataSet做中间层因为它的FieldDefs可以在运行时动态建不用提前设计表结构。关键属性就三个DataSource指向数据集KeyField指向主键字段ParentField指向父节点字段。父节点字段为空的行自动成为根节点其余按父子关系挂上去。这个逻辑和很多报表工具的树形展开是一样的但 FNC 把它做进了控件属性里不用写一行递归代码。3.2 建一个自关联数据集并绑到 TreeView下面这段代码建一个带ID、ParentID、Name三个字段的内存表插几条层级数据然后绑到TMSFNCTreeViewprocedure TForm1.BuildTreeData; begin ClientDataSet1.FieldDefs.Clear; ClientDataSet1.FieldDefs.Add(ID, ftInteger); ClientDataSet1.FieldDefs.Add(ParentID, ftInteger); ClientDataSet1.FieldDefs.Add(Name, ftString, 50); ClientDataSet1.CreateDataSet; ClientDataSet1.AppendRecord([1, 0, 总部]); ClientDataSet1.AppendRecord([2, 1, 研发部]); ClientDataSet1.AppendRecord([3, 1, 市场部]); ClientDataSet1.AppendRecord([4, 2, 前端组]); ClientDataSet1.AppendRecord([5, 2, 后端组]); ClientDataSet1.First; TMSFNCTreeView1.DataSource : ClientDataSet1; TMSFNCTreeView1.KeyField : ID; TMSFNCTreeView1.ParentField : ParentID; TMSFNCTreeView1.TextField : Name; TMSFNCTreeView1.Reload; end;AppendRecord按字段顺序填值ParentID为 0 的当根。Reload是必须调的否则控件不会重新读数据集。TextField指定显示哪个字段不设的话默认显示第一个字符串字段。如果层级没出来先检查ParentID的类型是不是和KeyField一致一个ftInteger一个ftString是绑不上的。3.3 点节点联动 Grid把选中行传给另一个控件TreeView 选完节点通常要联动右边 Grid 显示明细。FNC 的OnNodeClick事件里能拿到Node.Key用它去过滤数据集procedure TForm1.TMSFNCTreeView1NodeClick(Sender: TObject; ANode: TTMSFNCTreeNode); begin ClientDataSet2.Filter : DeptID ANode.Key; ClientDataSet2.Filtered : True; TMSFNCGrid1.Reload; end;ANode.Key就是KeyField对应的值。Filter字符串拼接在字段是数字时没问题如果是字符串字段要加引号。Filtered : True之后记得ReloadFNC 的 Grid 不会自动感知数据集过滤变化。这个联动模式在「delphi通过数据库实现treeview」这类需求里最常用比手动遍历节点快得多。4. 样式与圆角panel控件圆角、子控件间距怎么调4.1 FNC 的样式体系Appearance 和 Style 是两套东西FNC 控件的外观分两层Appearance管填充、边框、圆角这些几何属性Style管颜色主题。很多人搜「panel控件圆角」时以为改一个属性就行实际上 FNC 里圆角在Appearance.Rounding下是个TTMSFNCGraphicsRounding对象要分别设TopLeft、TopRight、BottomLeft、BottomRight四个角。我一般先设Appearance.Fill.Color给个底色再设Appearance.Stroke.Color和Stroke.Width画边框最后调Rounding。如果只设圆角不设填充圆角看不出来因为默认填充是透明的。4.2 给 Panel 加圆角和内边距的完整参数下面这段代码把一个TMSFNCPanel做成圆角卡片同时控制子控件间距procedure TForm1.StylePanel; begin // 圆角 TMSFNCPanel1.Appearance.Rounding.TopLeft : 12; TMSFNCPanel1.Appearance.Rounding.TopRight : 12; TMSFNCPanel1.Appearance.Rounding.BottomLeft : 12; TMSFNCPanel1.Appearance.Rounding.BottomRight : 12; // 填充和边框 TMSFNCPanel1.Appearance.Fill.Color : $00F5F5F5; TMSFNCPanel1.Appearance.Stroke.Color : $00CCCCCC; TMSFNCPanel1.Appearance.Stroke.Width : 1; // 内边距控制子控件离边界的距离 TMSFNCPanel1.Padding.Left : 16; TMSFNCPanel1.Padding.Top : 16; TMSFNCPanel1.Padding.Right : 16; TMSFNCPanel1.Padding.Bottom : 16; end;Padding是 FNC 控件通用的内边距属性设了之后子控件用Align : alTop排列时会自动留出间距。如果子控件之间还要额外间距用Margin属性或者干脆在子控件之间插一个空的TMSFNCSpacer。颜色值用的是 BGR 顺序$00F5F5F5在 Delphi 里是浅灰别按 RGB 写反了。注意FMX 下Appearance.Fill.Color的类型是TAlphaColorVCL 下是TColor同一段代码跨框架编译时这里要条件编译否则报类型不匹配。4.3 子控件间距的三种做法和适用场景做法属性适用场景注意父容器 PaddingPanel.Padding子控件统一离边界距离对所有子控件生效不能单独调子控件 MarginControl.Margin单个子控件周围留白需要父容器支持 Margin 布局插入 SpacerTMSFNCSpacer精确控制两个控件之间距离多一个控件布局文件变大我一般优先用 Padding 做整体留白个别控件用 Margin 微调。Spacer 只在需要固定像素间距且布局复杂时才用否则控件树会变得很难维护。FNC 的布局引擎对 Margin 的支持在 VCL 和 FMX 下略有差异FMX 下更接近 CSS 的盒模型VCL 下 Margin 有时会被忽略这点要有心理准备。5. 避坑与排查装完用不起来的那几件事5.1 编译报找不到 TMSFNCGraphics 单元现象装完 UI Pack新建工程拖控件编译时提示Unit TMSFNCGraphics not found。原因FNC Core 没装或者装了但 Library Path 里没加 Core 的源码目录。UI Pack 的 dpk 里requires了 Core 的包但 IDE 的搜索路径不会自动加。解决在 Tools → Options → Language → Delphi → Library 里给 Win32 和 Win64 各加一条D:\TMS\FNC\Core\source然后重新编译 UI Pack。加完路径后最好重启一次 IDE否则包缓存可能还是旧的。5.2 控件拖上窗体但运行时一片空白现象设计期能看到 Grid 的列头运行起来数据不显示或者 TreeView 没有节点。原因DataSource设了但数据集没Open或者Reload没调。FNC 控件不会自动监听数据集的AfterOpen必须手动触发一次刷新。解决在FormCreate里确保ClientDataSet.Open或CreateDataSet在绑DataSource之前执行绑完之后调Reload。如果数据是异步加载的在加载完成的事件里再调一次Reload。5.3 中文字体显示发虚或截断现象Grid 里的中文比英文模糊或者列宽不够时中文被截成半个字。原因FNC 默认字体是Segoe UI中文回退到系统默认字体时渲染质量下降。列宽按字符数算中文占两个字符宽度但控件按一个算。解决把TMSFNCGrid1.Font.Name设成Microsoft YaHei UI或SimSun字号至少 9。列宽不要用AutoSizeColumns自动算手动给中文列设Width : 120以上。如果还是截断检查Appearance.Stroke.Width是不是太粗挤占了文字空间。5.4 安装后 IDE 启动变慢或包冲突现象装完 FNC 后 Delphi 12.3 启动要等很久或者打开旧工程时提示包版本冲突。原因FNC 的包在 IDE 里注册了设计期包如果之前装过旧版本没卸干净两个版本的bpl会同时加载。解决先 Component → Install Packages 里把旧的 TMS 包全部 Remove再去注册表HKCU\Software\Embarcadero\BDS\23.0\Known Packages下删掉残留项然后重装。装完只保留一个版本的 FNC 包别 VCL 和 FMX 同时装两套不同版本的。5.5 数据库字段类型不匹配导致 TreeView 层级错乱现象TreeView 绑上去之后所有节点都成了根节点层级没出来。原因KeyField和ParentField的类型不一致比如ID是ftInteger而ParentID是ftString控件比较时永远不相等。解决建数据集时确保两个字段类型一致都是ftInteger或都是ftString。如果数据库里类型确实不同在TClientDataSet里加计算字段转换或者在OnCalcFields里统一成字符串再绑。6. 进阶用 FNC 做多框架复用的一个具体技巧FNC 最大的价值不是单个控件多好看而是同一套界面代码能在 VCL 和 FMX 下复用。我实际项目里的做法是把界面逻辑抽到一个TFrame里Frame 上只放 FNC 控件不写任何 VCL 或 FMX 专有代码。然后建两个工程一个 VCL 的一个 FMX 的各自uses这个 Frame 单元。具体步骤先建一个TFramedescendant在它上面放TMSFNCGrid、TMSFNCTreeView、TMSFNCPanel。所有事件处理里只用 FNC 自己的类型比如TTMSFNCTreeNode、TTMSFNCGridColumn不碰TTreeNode或TGrid。数据绑定用TClientDataSet因为它在 VCL 和 FMX 下都能用。// 公共 Frame 单元不引用 VCL 或 FMX 专有单元 unit uDataFrame; interface uses System.Classes, Data.DB, Datasnap.DBClient, TMSFNCGrid, TMSFNCTreeView, TMSFNCPanel; type TDataFrame class(TFrame) TreeView: TMSFNCTreeView; Grid: TMSFNCGrid; Panel: TMSFNCPanel; DataSource: TDataSource; ClientDataSet: TClientDataSet; procedure TreeViewNodeClick(Sender: TObject; ANode: TTMSFNCTreeNode); private procedure BuildData; public procedure Init; end; implementation procedure TDataFrame.Init; begin BuildData; TreeView.DataSource : DataSource; TreeView.KeyField : ID; TreeView.ParentField : ParentID; TreeView.TextField : Name; TreeView.Reload; Grid.DataSource : DataSource; Grid.Reload; end; procedure TDataFrame.BuildData; begin ClientDataSet.FieldDefs.Clear; ClientDataSet.FieldDefs.Add(ID, ftInteger); ClientDataSet.FieldDefs.Add(ParentID, ftInteger); ClientDataSet.FieldDefs.Add(Name, ftString, 50); ClientDataSet.CreateDataSet; ClientDataSet.AppendRecord([1, 0, 根节点]); ClientDataSet.AppendRecord([2, 1, 子节点A]); ClientDataSet.AppendRecord([3, 1, 子节点B]); ClientDataSet.First; end; procedure TDataFrame.TreeViewNodeClick(Sender: TObject; ANode: TTMSFNCTreeNode); begin ClientDataSet.Locate(ID, ANode.Key, []); end; end.这个 Frame 单元里没有VCL.Forms也没有FMX.Forms所以 VCL 工程和 FMX 工程都能uses它。VCL 工程里建一个TForm放一个TDataFrame的实例Align : alClientFMX 工程同理。这样一套界面逻辑维护两份壳改一处两边都生效。验证方法很简单在 VCL 工程里跑一遍确认 TreeView 层级和 Grid 联动正常然后不改 Frame 代码直接在 FMX 工程里编译运行看同样的交互是否成立。如果 FMX 下报错大概率是某个 FNC 控件的属性在 FMX 下类型不同比如颜色值这时候在 Frame 里用条件编译{$IFDEF FMX}包一下就行。我自己的习惯是新项目先建 Frame再建 VCL 壳跑通之后再建 FMX 壳。不要反过来因为 FMX 的布局约束比 VCL 严先在 FMX 下调好再往 VCL 移VCL 下通常不会出问题。这个顺序能省掉不少来回改布局的时间。希望帮到你。本文还有配套的精品资源点击获取
返回列表