繁体   English   中英

更改 Sysem.Variants.VarToWideStr 的区域设置格式

[英]Change the regional settings format for Sysem.Variants.VarToWideStr

我的应用程序上的第三方组件 (FastReports) 广泛使用 System.Variants.VarToWideStr 函数,这很好,只是它忽略了我需要该应用程序使用的区域设置。

例子:

FormatSettings.ShortDateFormat := 'dd/mm/yyyy';
ShowMessage(VarToWideStr(Date));
FormatSettings.ShortDateFormat := 'yyyy/mm/dd';
ShowMessage(VarToWideStr(Date));

此代码始终返回相同的字符串,忽略我指示要使用的应用程序的区域设置。

您是否知道另一种更改应用程序(具体为 VarToWideStr)将要使用的区域设置的方法?

我认为你被 Variants 单元和 FastReport 的糟糕设计搞砸了。 VarToWideStr调用VarToWideStrDef ,后者调用隐式_VarToWStr ,然后是DateToWStrViaOS ,最后VarBStrFromDate来自单元System.VarUtils VarBStrFromDate

事实上VarBStrFromDate是对函数的引用,它的实现取决于编译器。 在 Windows 32/64 上,这只是oleaut32.dllVarBstrFromDate的引用。 非 Windows 编译器回退到通过DateTimeToStr (单参数不变)转换值,它使用全局格式设置和“C”格式说明符来格式化值。

没有什么好的方法可以解决这个问题,因为所有这些例程都过多地依赖于全局状态。 幸运的是 (??) 您可以将VarBStrFromDate指向您自己的实现。 您可以从System.VarUtils单元的BackupVarBStrFromDate函数中看到的非 Windows 平台的默认实现中获得启发。 然后你可以做这样的事情:

uses
  System.SysUtils, System.Variants, System.VarUtils, System.DateUtils;

function MyVarBstrFromDate(dateIn: TDateTime; LCID: Integer; dwFlags: Integer;
  out bstrOut: WideString): HRESULT; stdcall;
begin
  if LCID = VAR_LOCALE_USER_DEFAULT then
  begin
    bstrOut := DateTimeToStr(dateIn);
    Result := VAR_OK;
  end
  else
    Result := VAR_NOTIMPL;
end;

{ ... }

System.VarUtils.VarBstrFromDate := MyVarBstrFromDate;
FormatSettings.ShortDateFormat := 'yyyy-mm-dd';
FormatSettings.LongTimeFormat := 'hh:nn:ss';
Writeln(VarToWideStr(EncodeDate(2019, 11, 29)));
Writeln(VarToWideStr(EncodeDateTime(2019, 11, 29, 10, 30, 50, 700)));

得到结果:

2019-11-29
2019-11-29 10:30:50

您需要注意,这会更改整个应用程序中依赖VarBstrFromDate的所有例程的行为。

VarToStr 另请参阅此处,作者建议在转换为字符串之前从变体中提取日期值。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM