更改Sysem.Variants.VarToWideStr的区域设置格式 [英] Change the regional settings format for Sysem.Variants.VarToWideStr

查看:92
本文介绍了更改Sysem.Variants.VarToWideStr的区域设置格式的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



示例:

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

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

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

解决方案

我认为您对Variants单元和FastReport的糟糕设计感到困惑。 VarToWideStr 调用 VarToWideStrDef 调用隐式 _VarToWStr ,然后是 DateToWStrViaOS ,最后从单元 System.VarUtils 中的 VarBStrFromDate



实际上 VarBStrFromDate 是对函数的引用,其实现取决于编译器。在Windows 32/64上,这仅是对 oleaut32.dll 中的VarBstrFromDate 。非Windows编译器会退回到通过使用全局格式设置和DateTimeToStr (单参数不变)转换值的过程。 /Libraries/Rio/en/System.SysUtils.DateTimeToString rel = noreferrer> C格式说明符以格式化该值。



有没有什么好的办法,因为所有这些例程都过于依赖全局状态。幸运的是,您可以将 VarBStrFromDate 指向您自己的实现。在单元 System.VarUtils 的函数 BackupVarBStrFromDate 中可以看到非Windows平台的默认实现的启发。然后,您可以执行以下操作:

 使用
System.SysUtils,System.Variants,System.VarUtils,System .DateUtils;

函数MyVarBstrFromDate(dateIn:TDateTime; LCID:Integer; dwFlags:Integer;
out bstrOut:WideString):HRESULT; stdcall;
开始
如果LCID = VAR_LOCALE_USER_DEFAULT,则
开始
bstrOut:= DateTimeToStr(dateIn);
结果:= VAR_OK;
结束
否则
结果:= VAR_NOTIMPL;
结尾;

{...}

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 也是如此。另请参见此处,作者建议在转换为字符串之前从变体中提取日期值。 p>

A third party component (FastReports) on my application is using extensively the System.Variants.VarToWideStr function, which is fine except that it ignores the regional settings I need that application to use.

Example:

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

This code always returns the same string, ignoring the regional settings that I indicate the application to use.

Do you know of another way to change the regional settings that the application (concretely VarToWideStr) is going to use ?.

解决方案

I think you're screwed by awful design of Variants unit as well as FastReport. VarToWideStr calls VarToWideStrDef which invokes implicit _VarToWStr, then DateToWStrViaOS and finally VarBStrFromDate from unit System.VarUtils.

In fact VarBStrFromDate is a reference to function and its implementation depends on compiler. On Windows 32/64 this is just a reference to VarBstrFromDate from oleaut32.dll. Non-Windows compilers fall back to converting the value via DateTimeToStr (single argument invariant) which uses global format settings and 'C' format specifier to format the value.

There is no good way around that, because all those routines depend too much on global state. Luckily (??) you can point VarBStrFromDate to your own implementation. You can get inspired by default implementation for non-Windows platforms seen in function BackupVarBStrFromDate of unit System.VarUtils. Then you can do something like this:

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)));

to get the result:

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

You need to be aware that this changes the behavior of all routines that rely on VarBstrFromDate throughout the entire application.

The same goes for VarToStr. See also here, where the author suggest extracting the date value from variant before conversion to string.

这篇关于更改Sysem.Variants.VarToWideStr的区域设置格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆