将VarToDoubleAsString使用Delphi设置(而不是操作系统设置)

5

当我们将一个包含字符串值的 Variant 分配给浮点变量时,Delphi 调用 VarToDoubleAsString 进行转换,VarToDoubleAsString 又通过 VarR8FromStr 使用操作系统设置的小数和千位分隔符进行转换。如果我们需要更改 SysUtils.DecimalSeparator 和 SysUtils.ThousandSeparator,则这会带来问题。例如运行以下程序:

program VarStrToFloat;

{$APPTYPE CONSOLE}

uses
  SysUtils,
  Math;

function FormatFloatUsingDelphiSettings(Value: Extended): string;
begin
  Result := FormatFloat('#,##0.00', Value);
end;

procedure Test(const AMsg: string);
var
  r1, r2: Extended;
  s1, s2: string;
  v: Variant;
begin
  r1 := 5432.1;
  s1 := FormatFloatUsingDelphiSettings(r1);
  v := s1; // <== conversion uses OS settings
  r2 := v;
  s2 := FormatFloatUsingDelphiSettings(r2);

  Write(AMsg: 8, s1: 10, s2: 10, '  ');
  if SameValue(r1, r2) then
    Writeln('OK')
  else
    Writeln('FAIL');
end;

procedure SwapEm;
var
  tmp: Char;
begin
  tmp := DecimalSeparator;
  DecimalSeparator := ThousandSeparator;
  ThousandSeparator := tmp;
end;

begin
  Test('Default');
  SwapEm;
  Test('Changed');
  Readln;
end.

第一个测试正常工作,第二个测试失败。

是否有一种方法可以使变量转换使用 SysUtils.DecimalSeparatorSysUtils.ThousandSeparator


1
我不知道有什么简单的方法来做到这一点。曾经有一种替换变量转换例程(SetVariantManager)的方法,但是在最近的版本中已经被删除了。好吧,它还在那里,只是没有任何作用。出于某些复杂的原因(QC#87786),我需要替换 _VarFromCurr。您可以通过替换 _VarToDouble 来实现所需的功能,但这可能会更加困难(涉及一些钩子)。当然,可能有一种官方的方法可以做到这一点,但我不知道..... - David Heffernan
1个回答

12

你可以根据自己的需求替换 varutils.pas 中的 VarR8FromStr 函数,然后 VarToDoubleAsString 会使用它:

function MyConversion(const strIn: WideString; LCID: Integer; dwFlags: Longint;
    out dblOut: Double): HRESULT; stdcall;
const
  CResult: array [False..True] of HRESULT = (VAR_INVALIDARG, VAR_OK);
var
  s: string;
begin
  s := StringReplace(StrIn, ThousandSeparator, '', [rfReplaceAll]);
  Result := CResult[TryStrToFloat(s, dblOut)];
end;

[...]

begin
  varutils.VarR8FromStr := MyConversion;
  [...]

+1 很好!不知道这个。可惜对我的“_VarFromCurr”问题没有帮助!! - David Heffernan
@David - 我看到了报告...如果VarCompareSimple中的CmpTypeMap是可替换的或元素是可分配的,那就太好了...为什么不能使用case TVarData(Value).VType of varDouble: if TVarData(Value).VDouble = 0.0 then,这样比较时就不涉及变量。 - Sertac Akyuz

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接