Delphi 2009 无法将 '' 与 333 进行比较,而 Delphi 6 可以:“无法将类型 (UnicodeString) 的变体转换为类型 (Double)”在 Delphi 2009

问题描述 投票:0回答:1

我正在尝试将带有

TdxDBGrid
的 Delphi 6 应用程序迁移到 Delphi 2009,暂时我想保留
TdxDBGrid
,因为它具有
TcxGrid
没有的功能(我们正在转向
TcxGrid
一般情况下)。当用户在
TdxDBGrid
:

中输入新行和新数值时,我陷入了这个错误

无法将类型 (UnicodeString) 的变体转换为类型 (Double)

我发现这个错误非常普遍 - 这一切都归结为

''
如何转换为
Double
(例如转换为 333)。 Delphi 2009 有这个例程(来自 Delphi RTL
Variants.pas
):

function VarToDoubleAsString(const V: TVarData): Double;
var
  S: WideString;
  LValue: Extended;
  LResult: HResult;
begin
  _VarToWStr(S, V);
  LResult := VarR8FromStr(S, VAR_LOCALE_USER_DEFAULT, 0, Result);
  case LResult of
    VAR_OK:; // in this case the OS function has put the value into result
    VAR_TYPEMISMATCH:
      if TryStrToFloat(S, LValue) then
        Result := LValue
      else
        VarResultCheck(VAR_TYPEMISMATCH, V.VType, varDouble);
  else
    VarResultCheck(LResult, V.VType, varDouble);
  end;
end;

但是Delphi 6有这个例程:

function VarToRealAsString(const V: TVarData): Extended;
var
  S: String;
  LValue: Double;
  LResult: HResult;
begin
  _VarToLStr(S, V);
  LResult := VarR8FromStr(S, $400, 0, LValue);
  if LResult = VAR_OK then
    Result := LValue
  else if not TryStrToFloat(S, Result) then                             
    VarResultCheck(LResult, varString, varDouble);  
end;

问题从

LResult := VarR8FromStr(S, VAR_LOCALE_USER_DEFAULT, 0, Result);
开始,其中返回类型不匹配,并且流程向下分支到
TryStrToFloat(S, LValue)
,不知何故失败。很难想象为什么
TryStrToFloat('', very-small-number)
会失败,但是这段代码:

function TryStrToFloat(const S: string; out Value: Extended): Boolean;
begin
  Result := TextToFloat(PChar(S), Value, fvExtended);
end;

表明

Try...
可能需要一个 Unicode 字符串,但到目前为止的所有处理都是通过
WideString
完成的,这就是转换通过以下方式完成的原因:

procedure _UStrFromWStr(var Dest: UnicodeString; const Source: WideString);
asm
        { ->    EAX pointer to dest                 }
        {       EDX pointer to WideString data      }
        
        XOR     ECX,ECX
        TEST    EDX,EDX
        JZ      @@1            // nil source => zero length
        MOV     ECX,[EDX-4]
        SHR     ECX,1          // length in WideString is byte count
@@1:    JMP     _UStrFromPWCharLen
end;

还有一些混乱。我不明白这部分,但要么:

  1. WideString
    ''
    无法转换为
    UnicodeString
    ,或
  1. very_small_number
    不适合作为默认值。

所以 - 如果我可以纠正这些

Variant
处理程序中的某些内容并将此更正的
Variants.pas
文件添加到我的项目中,那么我可以使用旧的
TdxDBGrid
一段时间。

那么 - 是否有人有类似的迁移问题的经验,正是这种类型的

Variant
处理、
Variant
转换代码,并且他们知道并且可以建议对
Variant
处理/转换程序进行或多或少的安全修正?

delphi devexpress variant delphi-2009 delphi-6
1个回答
0
投票

您可以更改 Delphi 将变量字符串转换为双精度型的方式。因此,您可以告诉 Delphi 将空字符串转换为值为 0.0 的双精度值。您可能会因此隐藏其他错误而不是修复它们。所以要小心。

uses VarUtils;

{$IF compilerversion >= 24}
function MyVarR8FromStr(const strIn: PWideChar; LCID: Integer; dwFlags: Integer;
  out dblOut: Double): HRESULT; stdcall;
const
  CResult: array [False..True] of HRESULT = (VAR_TYPEMISMATCH, VAR_OK);
begin
  if StrLen(strIn) = 0 then
  begin
    Result := VAR_OK;
    dblOut := 0.0;
  end
  else
    Result := CResult[TryStrToFloat(strIn, dblOut)];
end;
{$ELSE}
function MyVarR8FromStr(const strIn: WideString; LCID: Integer; dwFlags: Longint;
    out dblOut: Double): HRESULT; stdcall;
const
  CResult: array [False..True] of HRESULT = (VAR_TYPEMISMATCH, VAR_OK);
begin
  if strIn = '' then
  begin
    Result := VAR_OK;
    dblOut := 0.0;
  end
  else
    Result := CResult[TryStrToFloat(strIn, dblOut)];
end;
{$IFEND}

initialization
  VarUtils.VarR8FromStr := MyVarR8FromStr;
end.
© www.soinside.com 2019 - 2024. All rights reserved.