在给一个旧 VCL 示例增加 Delphi 5 兼容性时,项目在一行对新版 Delphi 来说完全正常的代码上失败了。该代码试图直接给 TDateTimePicker.Format 属性赋自定义日期格式。
|
1 |
DateTimePicker.Format := 'MM/dd/yyyy'; |
TDateTimePicker 是 Windows common control 的 VCL 封装。新版 Delphi 提供了方便的 Format 属性,但 Delphi 5 没有。在 Delphi 5 及更早版本中,控件通常会跟随 Windows 区域日期设置,除非直接向底层 common control 发送消息。
Delphi 5 使用 common-control API
兼容性修复是在 Delphi 5 分支中调用 CommCtrl 单元里的 DateTime_SetFormat,同时让新版编译器继续使用直接属性赋值。编译 Delphi 5 分支时,需要把 CommCtrl 加入 uses。
|
1 2 3 4 5 |
{$IFDEF D5} DateTime_SetFormat(DateTimePicker.Handle, PChar('MM/dd/yyyy')); {$ELSE} DateTimePicker.Format := 'MM/dd/yyyy'; {$ENDIF} |
为什么 ShortDateFormat 不够
修改 Delphi 的全局日期格式变量,并不能可靠改变由 Windows common control 支撑的日期时间选择器。控件按照自身设置和收到的消息渲染,这就是 Delphi 5 中应使用 DateTime_SetFormat 的原因。
这种区别对跨版本示例尤其重要。Delphi 7 或 Delphi 2009 中干净的一行代码,在 Delphi 5 中可能根本不存在;而 Windows common-control 消息仍可使用。条件编译能让每个编译器走最自然的路径。
测试旧版本兼容性
应用修复后,同时测试显示值和保存值。格式只影响用户看到的内容,不应改变计算使用的底层 TDateTime 值。在订单、发票和电子表格导出中,显示格式与数值日期保持一致非常重要。
如果控件句柄被重建,也要重新检查格式。某些 VCL 控件在销毁并重新创建窗口句柄后会丢失原生控件状态。若应用运行时改变样式或父控件,请在句柄可用后再应用格式。
当项目不再需要 Delphi 5 支持时,可以删除条件分支,只保留直接的 Format 属性赋值。在此之前,把兼容代码放在控件初始化附近,说明它是 VCL 控件限制的 workaround,而不是业务计算逻辑的一部分。