我正在将我的Delphi 5应用程序迁移到Delphi XE3。我在编译时得到了一些错误。有人可以帮我解决这些问题。提前感谢您的帮助。
我无法在XE3中找到函数OemToChar
的定义。当我按住Ctrl键并单击该功能时,它会显示消息Unable to locate 'WinAPI.Windows.pas'
。我无法打开任何delphi组件文件。 windows.pas位于系统上的位置是什么?或者如何解决?
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;
'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;
答案 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)
'OemToChar()'在'Winapi.Windows.pas'中声明,就像IDE所说的那样。如果uses
子句包含“Windows”,请确保Winapi.Windows
子句包含Winapi
,或者uses
包含在项目选项的“单位范围名称”字段中相反(自从你迁移后它可能会这样做。)
在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世界中也很少使用它们。
另一种情况,您现在需要重新编写代码以便考虑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