如何修复Delphi XE3迁移错误?

时间:2012-12-10 21:34:56

标签: delphi delphi-5 delphi-xe3

我正在将我的Delphi 5应用程序迁移到Delphi XE3。我在编译时得到了一些错误。有人可以帮我解决这些问题。提前感谢您的帮助。

  1. 我无法在XE3中找到函数OemToChar的定义。当我按住Ctrl键并单击该功能时,它会显示消息Unable to locate 'WinAPI.Windows.pas'。我无法打开任何delphi组件文件。 windows.pas位于系统上的位置是什么?或者如何解决?

  2. 以下函数中的
  3. Incompatiable Types: 'PAnsiChar' and 'PWideChar'OemToChar(p1, p2)一致。

  4. function OemToAnsi(const Str: string): string;
    var
      p1,
      p2: PChar;
    begin
      p1 := PChar(Str);
      p2 := StrNew(p1);
      OemToChar(p1, p2);
      Result := StrPas(p2);
      StrDispose(p2);
    end;
    
    1. 在以下代码中获取错误'Low Bound Exceeds High Bound'
    2. function StrToRichText(const Str: string): string;
      var
        i: integer;
      begin
        Result := '';
        for i := 1 to Length(Str) do
        begin
          case Str[i] of
            #128 .. #255 :
              Result := Result + '\''' + LowerCase(IntToHex(Ord(Str[i]), 2));
            '\','{','}':
              Result := Result + '\' + Str[i];
          else
            Result := Result + Str[i];
          end;
        end;
      end;
      

3 个答案:

答案 0 :(得分:7)

您的OemToAnsi功能应如下所示:

function OemToAnsi(const Str: AnsiString): AnsiString;
begin
  SetLength(Result, Length(Str));
  OemToCharA(PAnsiChar(Str), PAnsiChar(Result));
end;

但也许你会更好用

function OemToWide(const Str: AnsiString): string;
begin
  SetLength(Result, Length(Str));
  OemToChar(PAnsiChar(Str), PChar(Result));
end;

至于你的StrToRichText,这看起来更难。它显然只接受ANSI输入。如果你想坚持ANSI,那么只需将声明更改为

function StrToRichText(const Str: AnsiString): AnsiString;

RTF使用7位ASCII编码。要使该功能与Unicode输入一起使用,您需要使用序数> = 128来转义任何字符。例如,在Wikipedia Rich Text Format页面上描述了转义。我会把它作为锻炼给你!


在你走得更远之前,你需要阅读MarcoCantù的白皮书:Delphi and Unicode

答案 1 :(得分:4)

  1. 'OemToChar()'在'Winapi.Windows.pas'中声明,就像IDE所说的那样。如果uses子句包含“Windows”,请确保Winapi.Windows子句包含Winapi,或者uses包含在项目选项的“单位范围名称”字段中相反(自从你迁移后它可能会这样做。)

  2. 在D2009 +中,OemToChar()现在映射到OemToCharW(),而不再映射到OemToCharA()。两个函数的第一个参数是PAnsiChar。在D2009 +中,PChar现在映射到PWideChar,而不再映射到PAnsiChar,因此您需要相应地重新编写代码,例如:

    function OemToAnsi(const Str: AnsiString): string;
    var
      S: String;
    begin
      SetLength(S, Length(Str));
      OemToChar(PAnsiChar(Str), PChar(S));
      Result := PChar(S);
    end;
    

    但是,你应该重新思考为什么你仍然需要首先处理OEM字符串。它们在Unicode世界中没有多大意义,甚至在Ansi世界中也很少使用它们。

  3. 另一种情况,您现在需要重新编写代码以便考虑Char=WideChar,因为字符范围远大于Ansi字符范围。你我会使用序数代替(你也应该正确地考虑UTF-16代理人,但我会把它作为练习),例如:

    function StrToRichText(const Str: string): string;
    var
      i: integer;
    begin
      Result := '';
      for i := 1 to Length(Str) do
      begin            
        case Ord(Str[i]) of
          128..255:
            Result := Result + '\''' + LowerCase(IntToHex(Ord(Str[i]), 2));
          Ord('\'), Ord('{'), Ord('}'):
            Result := Result + '\' + Str[i];
        else
          Result := Result + Str[i];
        end;
      end;
    end;
    

答案 2 :(得分:1)

关于Unicode,您已经得到了解决。谷歌也有很多文章。


我还建议您阅读有关类助手和记录助手的内容 - 这可能会帮助您在库中重新引入一些过时的函数,并延迟重新编写代码库。

这也可以帮助您覆盖

等错误
var r: TRect;
 ....
  with r do begin
 ....
     B := IntersetRect( A1, A2 );
 ....
  end;

关于OemToChar - 我邀请你最好使用方便的包装器,这是在Delphi的RxLib中给出的5次,然后你将迁移到Jedi Code Library并且你的代码会只是没有那个问题。

然而现在你在XEn - 没有那个你就可以完美地生活 http://docwiki.embarcadero.com/Libraries/XE2/en/System.SetCodePage

 var sa, so: RawByteString;
 ....
     sa := source; SetCodePage(sa, GetACP(), true);
     so := sa;     SetCodePage(so, GetOEMCP(), true);

类似的代码在我的项目中有效,我解析传统的二进制数据。

如果您只关心一个区域设置,那么您可能会对此进行硬编码。

 var sa: AnsiString[1251]; so: AnsiString[866]; su: UnicodeString;
 ....
     sa := source; 
 ....
     su := sa; // Win32: MultiByteToWideCharBuf - official Microsoft way
     so := su; // Win32: WideCharToMultiByteBuf - official Microsoft way
 ....
     so := sa;  // double conversion in one step
     // did not tested, but should work accorrding to doc.   
     // looks like obsolete Win16 OemToChar
     // and like codepage-to-codepage direct transcoding
     //     routines from JCL.SF.NET