4

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

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

  2. Incompatiable Types: 'PAnsiChar' and 'PWideChar'在下面的函数中与OemToChar(p1, p2).

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'在以下代码中出现错误。

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

3 回答 3

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页面上进行了描述。我会把它作为练习留给你!


在更进一步之前,您需要阅读 Marco Cantù 的白皮书:Delphi 和 Unicode

于 2012-12-10T21:46:09.350 回答
4
  1. 'OemToChar()' 在 'Winapi.Windows.pas' 中声明,就像 IDE 所说的那样。确保您的uses子句包含Winapi.Windows,或者Winapi如果子句包含“Windows”,则包含在项目选项中项目的“单元范围名称”字段中uses(因为您正在迁移,它可能会这样做)。

  2. 在 D2009+ 中,OemToChar()映射到OemToCharW()现在,OemToCharA()不再映射。这两个函数的第一个参数是 a 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;
    
于 2012-12-10T21:56:35.627 回答
1

关于 Unicode,您已经得到解决。google上也有很多文章。


我还建议您阅读有关类助手和记录助手的信息——这可能有助于您在库中重新引入一些过时的函数,并延迟代码库的重新工作。

这也可以帮助您覆盖错误,例如

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

关于OemToChar- 你最好使用方便的包装器,RxLib在 Delphi 中给出了 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
于 2012-12-11T11:19:06.697 回答