简介:在Windows桌面开发领域,VCL控件库一直是Delphi开发者提升界面效率的关键工具。DevExpress VCL作为主流的第三方组件集,通过提供网格、下拉框、日期编辑等现成控件,帮助开发者在Win32/Win64平台上减少自绘工作量。其20.2.x系列针对RAD Studio 10.4做了适配,而20.2.4作为后期修正版,解决了编译器兼容性问题。合理选型并正确安装dcl设计时包与运行时bpl,是保障cxGrid等控件正常工作的前提。本文从版本配对、包类型区分、安装编译流程入手,结合常见故障处理,为维护10.4项目的工程团队提供一套可落地的配置参考。
1. DevExpress VCL 20.2.4 值不值得装:给 10.4 开发者的一个版本快照
DevExpress VCL 20.2.4 这份资源,是给还在用 RAD Studio 10.4 的 Delphi 开发者准备的控件库版本快照。装了它,IDE 里会多出十几个组件页,网格、下拉、日期、Ribbon 界面这些高频需求就不用自己自绘一遍了。它解决的是桌面 Win32/Win64 项目里“原生控件不够用、自绘又费时”的老问题。适合谁?手上有 10.4 老项目要维护、团队不想为换控件库而改 IDE 版本的人。如果你正打算把 VCL 项目的界面层重写一遍,这份资源能省下大量重复造轮子的时间。
2. 版本与选型:20.2.4 与 RAD Studio 10.4 的配对关系,包类型别搞混
2.1 版本矩阵不是玄学:20.2.4 在 20.2.x 体系里的位置
先澄清一个经常被弄混的点。DevExpress VCL 的版本号主干是 20.2.x,其中的 .4 是该系列里较后期的修正状态,不是跨越 IDE 主版本的大版本跳跃。20.2.4 对应的 IDE 主版本是 RAD Studio 10.4,意味着它的运行时单元和设计时包内部针对 10.4 的 Win32、Win64 编译器做了适配。直接装到更高版本的 RAD Studio 上,可能因为编译器内部接口变化而编不过。所以判断一份控件库资源能不能用,第一件事就是对齐 IDE 版本号。
这是我在维护项目时用的一个粗略对应表,按常见情形整理:
| IDE 版本 | 常见控件库版本区间 | 说明 |
|---|---|---|
| RAD Studio 10.4 | 19.x ~ 20.2.x(含 20.2.4) | 20.2 系列后期修复相对完整 |
| RAD Studio 11 | 21.x 起 | 控件库版本主干随 IDE 升级 |
| RAD Studio 10.3 | 18.x ~ 19.x | 旧工程长期维护常见组合 |
注意“区间”是个概念,不是严格约束。同一个小版本可能同时支持两代 IDE,但安装时安装器一般会自动检测当前 IDE,只亮出可用项。真正常见的问题不是装不上,而是装完选了错误目录里的包。
2.2 选型理由:为什么我倾向保留 20.2.4 而不是追更高版本
这里说一个我在项目里的实际取舍。团队某个管理系统从 10.3 时代升级到 10.4 时,界面层用了大量 DevExpress VCL。当时面临两个选择:继续用 19.x 老版本,还是跳到 20.2.4。我最后选了后者,原因是老版本在 10.4 的 Win64 编译环境下个别单元会触发编译警告升级成错误,而 20.2.4 的发布说明里明确处理过这一类编译器兼容问题。换 IDE 后第一步永远是“跑通编译”,任何在编译器升级后还要额外改源码的控件库都会拖慢迁移进度。
还有一个现实原因:许多团队的数据字典、报表模板、界面布局配置文件都已经按 20.2.x 的格式存了一遍,退回 19.x 意味着要重导布局文件。保存一个和 IDE 同代际、又处于修复后期的版本,是性价比最高的选择。不要指望控件库的每个小版本都值得追,重点是把版本号和工程里用到的功能面钉死。
2.3 必须先分清的两类包:dcl*.bpl 和普通 *.bpl
安装阶段最容易翻车的地方就在这里。DevExpress VCL 安装完成后,IDE 里加载的是 dcl 开头的设计时包,例如 dclcxGrid.bpl;普通 bpl 是运行时包,例如 cxGrid.bpl。dcl 包只在 IDE 里被加载,负责提供组件图标和设计期编辑器;运行时包则在编译产物运行时被加载。两者不是同一个文件,也不要混在一起处理。
要强调一个细节:控件库的库目录里会按 Delphi 版本和 C++ Builder 版本分目录存放。Delphi 10.4 要选内部编译器版本号对应的子目录,选错的话 dcl 包加载时直接报“无法定位包”。我一般会先记下当前 IDE 的编译器版本号,再进到库目录核对路径,而不是凭经验随便点。这个习惯在后续排错时能省下很多时间。
3. 安装与编译:从运行库到组件面板出现,完整配置流程
3.1 安装前的三项环境检查
动手装之前,先把环境里的旧包袱清理掉。第一项,确认 RAD Studio 10.4 本体已经装完,并在 About 窗口里能看到当前 Update 版本。第二项,在控制面板里检查是否残留旧版 DevExpress VCL,有残留就先卸载干净,否则安装器可能把新文件并进旧目录,造成两套运行时单元混用。第三项,确认安装目录可写。
我自己每次安装前都会在记事本里列一个环境检查清单,包括 IDE 版本号、Update 号、是否安装过其他控件库、管理员权限是否可用。逐项过完再双击安装包,不要装到一半被权限弹窗打断,再回头折腾。这一步不需要任何技术含量,但能挡住后面大多数奇怪报错。
3.2 安装过程中选什么:组件和平台
安装向导里的选项比看起来多:语言、IDE 平台、组件集。平台只要选 Win32 和 Win64 就够,不需要装跨平台移动设备的单元,那部分在 VCL 工程里不参与编译,却会拖慢安装过程。组件集建议全选,原因很简单:cxGrid 默认依赖一批公共运行时单元,只勾选局部组件容易漏掉依赖项,装完一编译就报找不到单元。全选虽然占用磁盘多一点,但后续功能扩展不用重新跑一遍安装器。
安装目录建议保持默认,不要为了“看起来整洁”把控件库装到中文路径或带空格的深层目录。DevExpress VCL 的批处理编译脚本对路径中的空格处理得不算友好,装到过深的路径会让后续手动编译时出现奇怪的脚本中断。
3.3 编译运行库:手动批处理的通用思路
安装程序一般自带编译步骤,但不少离线资源包装完需要自己触发一次全量编译。下面这段批处理示意我在多台机器上验证过的处理方式:
cd /d "C:\Program Files (x86)\DevExpress\VCL" set DEVDIR=%CD% for /r %DEVDIR%\Library\Delphi\Win32\Release %%i in (*.dproj) do ( msbuild "%%i" /p:Config=Release /p:Platform=Win32 /m )逻辑说明:第一行进入 DevExpress VCL 根目录,DEVDIR 保存当前路径;然后递归遍历 Library 目录下所有版本子目录里的 dproj 工程文件,用 msbuild 逐个以 Release 配置编译。加 /m 参数让 msbuild 并行编译,能明显缩短全量编译时间。加 /p:Platform=Win32 是明确只编 Win32,避免和后续 Win64 工程混在一起。
参数说明:这段脚本是通用示意,不是官方脚本。不同资源包的目录结构有差异,实际使用前先确认库文件放在 Library 的哪个子目录。如果本机装了多个 Delphi 版本,Library 下会存在多个版本子目录,编译时只进入当前 IDE 对应的那一个,不要全编。
3.4 IDE 集成:让组件面板出现,并配置搜索路径
编译完成后,把设计时 dcl 包注册进 IDE。打开 RAD Studio 10.4,在主菜单找到 Component → Install Packages,在对话框里点 Add,进入 dcl 包所在目录,把需要的 dcl 开头的 bpl 全部选中。确认后 IDE 会逐个加载,加载成功时组件面板会多出 “DevExpress” 开头的页面,例如 cx 开头的常用控件页和 dx 开头的增强控件页。
然后还要配置库路径,否则编译自己的工程时 IDE 找不到运行时单元。打开 Tools → Options 里的 Library 配置,把 DevExpress VCL 的源码目录和编译输出目录加到 Search Path。这一步漏了的话,IDE 在打开含 cxGrid 的窗体时会报 “Class TcxGrid not found”。
提示:全量编译 dcl 包耗时较长,可以先只编译 dcl 开头的设计时包,验证 IDE 能识别组件后,再把剩余运行时包补编完。
4. 控件落地实战:cxGrid、cxLookupComboBox、cxDateEdit 与 Ribbon 配置要点
4.1 cxGrid 的层级关系与数据绑定方式
cxGrid 是这批控件里使用频率最高、结构也最容易懵的。它分三层:外层是 TcxGrid 容器,中层是 TcxGridDBTableView 视图,底层是 DataController。绑定数据的核心代码是:
cxGrid1DBTableView1.DataController.DataSource := DataSource1; cxGrid1DBTableView1.Columns[0].DataBinding.FieldName := '订单号'; cxGrid1DBTableView1.DataController.BeginUpdate; try cxGrid1DBTableView1.CreateColumn; // 循环为其他数据集字段建列 finally cxGrid1DBTableView1.DataController.EndUpdate; end;逻辑说明:第一行把视图的 DataController 关联到普通 DataSource,DataSource 再指向数据集,和原生 DBGrid 的做法类似。第二行把第一列绑到“订单号”字段。后面三段代码演示了批量改列结构的标准姿势:先 BeginUpdate,此时视图暂停重绘和布局计算,建完列之后 EndUpdate 一次性刷新。如果不加这两句,在每个 CreateColumn 之后都会触发重绘,列多的时候界面会明显闪烁。
参数说明:BeginUpdate 和 EndUpdate 必须成对出现,中间尽量不写会抛异常的逻辑,否则遗忘 EndUpdate 会让视图停留在禁止刷新状态。正确写法就是用 try...finally 把 EndUpdate 放在 finally 里,保证异常时也一定能恢复。这条习惯在批量初始化列时尤其重要。
4.2 cxLookupComboBox 下拉框的关键参数
原生 TDBLookupComboBox 在数据量稍大时表现一般,cxLookupComboBox 主要强在下拉面板按需加载和显示字段组合。下面是配置示例:
cxLookupComboBox1.Properties.ListSource := dsCategory; cxLookupComboBox1.Properties.KeyFieldNames := 'id'; cxLookupComboBox1.Properties.ListFieldNames := 'name;code'; cxLookupComboBox1.Properties.ClearKey := 46;逻辑说明:ListSource 是下拉面板的数据源,KeyFieldNames 是实际写入当前记录关联值的字段,ListFieldNames 指下拉列表显示哪几个字段,多个字段用分号隔开——这样做可以显示“名称+编码”两列的宽下拉。最后一行 ClearKey 设成 46,表示按下 Del 键时清空当前选中的值。
参数说明:ListFieldNames 里的字段顺序就是下拉列表列顺序;想让某列宽度不同,需要配合 Properties 下的 Columns 编辑器手动加列,而不是只写字段名。ClearKey 不设的话,用户想清空下拉只能靠程序赋值,操作体验会差一截。另外,如果数据源里有重复键值,cxLookupComboBox 默认只显示第一条匹配项,要在业务层先去重。
4.3 cxDateEdit 日期编辑与 dxRibbon 界面改造
日期编辑控件在 VCL 工程里几乎每个表单都有。我常用的配置是把日期按钮开关打开:
cxDateEdit1.Properties.DateButtons := [btnToday, btnNow, btnClear]; cxDateEdit1.Properties.SaveTime := False; cxDateEdit1.Properties.InputKind := ikISO;逻辑说明:第一行设置下拉日期面板上的三个按钮:今天、当前时间、清空。第二行表示不保存时间部分,只保留日期,对生日、发货日期这类字段合适。第三行 InputKind 设置成 ikISO,要求用户按 2024-05-16 这种格式输入,避免不同系统区域设置下的斜杠日期产生歧义。
Ribbon 则是界面层的重头戏。把一个普通 Form 改成 Ribbon 风格,只需要把 TForm 的继承类换成 TdxRibbonForm,然后在窗体上放一个 TdxRibbon,再在 TdxRibbonPage 里建 TdxRibbonTab。我一般会把菜单栏、工具栏全部迁移到 Ribbon 页面里,然后停用旧 TMainMenu,这样窗体顶部只保留一套界面元素。需要注意 dxRibbonForm 的边框样式和普通窗体不同,窗口尺寸变化时状态栏和 Ribbon 的高度自适应逻辑要重新检查一遍。
4.4 cxLocalizer 界面本地化的初始化
如果交付对象是国内客户,控件内置的右键菜单和编辑器弹窗默认是英文。DevExpress VCL 提供了一套本地化组件,常见做法是在主窗体的 OnCreate 里加载语言资源:
cxLocalizer1.Locale := 2052; cxLocalizer1.Active := True;参数说明:Locale 填 2052 对应简体中文,Active 设为 True 后,组件库内部的默认菜单文字会切换成中文。前提是语言资源文件已经被编译进工程或放在可执行文件同目录下。如果 Active 设置后界面还是英文,优先检查资源文件有没有被正确打包,而不是怀疑代码写错。下面第 5 章会专门展开这个故障。
5. 安装使用避坑:五个高发故障的现象、原因与处理记录
5.1 打开 IDE 报错 “Can't load package ... dcl*.bpl”
现象:安装完成后重启 RAD Studio 10.4,启动过程弹窗提示某个 dcl 开头的 bpl 无法加载,IDE 继续启动但组件面板里找不到 DevExpress 页面。
原因:绝大多数情况是安装时把 Delphi 版本的包和 C++ Builder 版本的包装混了。同一个功能有两套编译产物,dcl 包内部引用的运行时包不同,IDE 加载时按内部导入表解析,版本对不上就会失败。
处理:先到库目录里确认 dcl 包所在子目录对应当前 IDE 的版本路径,把错装的包从 Install Packages 列表移除,再重新添加正确路径下的包。我还会打开 IDE 的 View → Packages 检查加载状态,而不是只看组件面板有没有出现页面——面板有时会缓存。
5.2 编译出来的 EXE 在别的机器上运行提示找不到 bpl
现象:开发机运行正常,拷贝 EXE 到测试机双击报错,弹窗显示找不到某个 cx 开头的 bpl 文件。
原因:工程默认用的是运行时包动态链接,生成的 EXE 不包含控件库代码,运行时要到系统路径或 EXE 同目录找对应 bpl。测试机没装控件库,自然缺文件。
处理:两个方向。要么在 Project → Options → Packages 里把 “Build with runtime packages” 勾掉,让控件库静态编译进 EXE——编译时间会变长,EXE 体积增大 20MB 以上,但分发省事;要么在发布目录里放全需要的 bpl,并把路径写进 PATH。做 ERP 类客户端我一般选静态链接,做模块化插件架构才保留动态 bpl。
5.3 cxGrid 上万行数据刷新时界面明显卡顿
现象:数据集刷新后调用 cxGrid 的 DataController 大量更新行,界面像一帧一帧地动,滚动时掉帧严重。
原因:没有合理使用 BeginUpdate 和 EndUpdate,或者每次数据变更都触发了视图的布局计算和绘制。还有一个容易被忽略的因素:如果打开了 View 的自动列宽或自动分组,任何数据变化都可能触发一整套重新布局。
处理:按前面 4.1 里的方式,把对 DataController 的结构调整包在 BeginUpdate/EndUpdate 中;对单纯的数据刷新,先把视图和主办单的刷新挂起,等数据集加载完再恢复显示。实际项目里能做到这两步,20000 行的刷新耗时能压到几百毫秒级别。
5.4 cxLocalizer 设置 Active 后界面仍是英文
现象:在程序里设置了 Locale 为 2052 并且 Active 为 True,编译运行后控件右键菜单还是英文。
原因:本地化资源没有真正进入编译产物。IDE 环境下资源可能从源码目录读到,但发布时没有附带语言文件,或者资源被放到 IDE 不知道的路径。
处理:检查工程包含的资源文件列表,确认语言资源已经加入编译;如果发布目录是干净的,把语言资源文件复制到 EXE 同目录,再做一次干净编译。这个故障我排查过两次才彻底理解:先查资源再查代码顺序,能少走弯路。
5.5 升级后旧工程打开窗体报 “Class not found” 或包重复加载
现象:从旧版本控件库迁移到 20.2.4 后,打开含 DevExpress 控件的窗体时 IDE 提示找不到某个类,或者 Install Packages 里同一个包出现两次。
原因:旧版本的 dcl 包没有被完全移除,多个版本的包同时指向同类名,IDE 加载顺序不稳定;新旧运行时包混杂也会导致 DFM 流里类名前缀解析失败。
处理:控制面板卸载旧控件库后,检查 Program Files 和用户文档目录下是否残留旧库文件,清理干净后重装 20.2.4。然后打开 IDE 的 Install Packages 列表,逐个移除重复项。还有一个场景最费时间:工程文件里的搜索路径仍然指向旧库目录,编译时新旧头文件混合。升级后第一件事就是全局搜索工程里的库路径,统一替换成新目录。
6. 验证安装是否完整,以及我每次装完必做的一步
6.1 三分钟验证法
装完别急着开工,先花三分钟验证。新建一个 VCL 工程,从组件面板拖一个 cxGrid 到窗体上,双击进入列编辑,确认设计时编辑器能打开;再从面板里拖一个 cxDateEdit,运行程序测试日期下拉面板显示中文。这两步能覆盖设计时包加载和运行时包分发两个层面。如果都正常,说明当前 IDE 环境下的安装基本完整。
再进一步,可以写一个最小测试函数,在程序启动时创建一组控件实例:
with TcxGrid.Create(nil) do try // 创建后立即释放,验证运行时包已正确链接 finally Free; end;只要这段代码能编译运行,运行时 bpl 的依赖已经满足,后续业务功能开发不会再撞上缺包问题。
6.2 把包注册状态导出一份存档
我自己的固定习惯是安装配置完成后,把 IDE 的包注册状态完整备份一次:导出注册表里 DevExpress 相关的 Known Packages 键为 reg 文件,再把 IDE 里项目搜索路径列表截图或导出文本,一起放进工程的 docs 目录。这样如果哪天重装系统、重装 IDE,不用凭记忆重新添加包路径和搜索路径,直接按存档恢复就行。
这个习惯帮我少填了很多次同样的坑。特别是团队里有多个开发机时,把这份存档同步给其他人,每个人装完环境都能保持一致,不会出现“你这台机器能编译我那台报错”的尴尬。从那以后我每次换机器都强制走一遍这个备份流程。
最后留一句给同样在 10.4 上维护项目的朋友:把版本号钉死、把包类型记清楚,这套控件库在 VCL 项目里能省的时间,远比安装时那几分钟多。希望帮到你。
本文还有配套的精品资源,点击获取