在 Delphi 2007 年的字符串中插入表情符号

Insert an emoji inside a string in Delphi 2007

我正在尝试完全按照标题所说的那样,在 Delphi 2007 年的字符串中插入表情符号,就像下面的示例一样:

procedure TForm1.Button1Click(Sender: TObject);
var s : string;
begin
s := 'This is my original string (y)';
s := ansireplacestr(s,'(y)','');
showmessage(s);
end;

我什至可以将表情符号粘贴到 IDE 的代码中,但在运行时 showmessage 结果如下:

这是我原来的字符串????

有没有办法在 Delphi 2007 年完成此任务?由于多种原因,我现在无法升级 Delphi。

有人说我的问题已经解决了这个话题:

Handling a Unicode String in Delphi Versions <= 2007

但是这个话题只是说使用third-party个组件,并没有具体说明如何使用。

编辑:在建议之后,我尝试使用函数 pos、delete 和 insert 以及一个宽字符串变量:

function addEmoji(mystring : widestring) : widestring;
var r, aux : widestring;
p : integer;
begin
r := mystring;
while pos('(y)',r) > 0 do
  begin
    aux := r;
    p := pos('(y)',aux);
    Insert('',aux,p);
    delete(aux,pos('(y)',aux),3);
    r := aux;
  end;
result := r;
end;

但结果是“(y)”被“????”替换了。

在 Delphi 2007 中,默认 string 类型为 AnsiString。表情符号需要 Unicode 处理,因为它们使用的高 Unicode 代码点在最常用的 Ansi 编码中根本不 fit/exist。因此,您需要改用 Unicode UTF 编码(UTF-7、-8、-16 或 -32)。

您可以对 UTF-7 使用 AnsiString1,或对 UTF-8 使用 UTF8String2 ,或 WideString 对于 UTF-16,或 UCS4String3 对于 UTF-32。

1: UTF-7 是一种 7 位 ASCII 兼容编码。

2UTF8String 确实存在于 Delphi 2007 中(它在 Delphi 6 中引入),但它不是 true UTF-8 字符串类型,它只是 AnsiString 的别名,期望它始终保存 UTF-8 编码数据。您必须使用 UTF8Encode()UTF8Decode() 来确保通过 UTF-16 正确转换为其他编码。 UTF8String 直到 Delphi 2009 年才成为 true UTF-8 字符串类型(UTF8Encode()UTF8Decode() 也被弃用)。

3UCS4String从Delphi6开始也存在,但它根本不是真正的字符串类型(即使在现代Delphi 版本)。它只是 array of UCS4Char.

的别名

RTL 没有对 UTF-7 的任何原生支持(但手动实现并不难),对 UTF-32 的支持也很少(只是为了方便 UTF-16 <-> UTF 之间的转换-32),因此您应该在代码中坚持使用 UTF-8 或 UTF-16。

如果将 UTF 数据转换为 Ansi,例如将 WideString 传递给 ShowMessage(),您将丢失表情符号数据。您可以将 WideString 传递给 Win32 API MessageBoxW() 函数,并且您不会丢失任何数据,但是表情符号可能会或可能不会正确显示,具体取决于所使用的字体对话框(但至少不会显示为 ??)。

但是,Delphi 2007 中的原生 RTL 根本不支持您正在尝试的内容,至少不支持 UTF-16。您将不得不找到基于第 3 方 WideString 的函数,或者使用 RTL 的 Pos()Delete()Insert() 内部函数编写您自己的函数,这些函数为WideString 数据,例如:

function WideReplaceStr(const S, FromText, ToText: WideString): WideString;
var
  I: Integer;
begin
  Result := S;
  repeat
    I := Pos(FromText, Result);
    if I = 0 then Break;
    Delete(Result, I, Length(FromText));
    Insert(ToText, Result, I);
  until False;
end;

var
  s : WideString;
begin
  s := 'This is my original string (y)';
  s := WideReplaceStr(s, '(y)', '');
  MessageBoxW(0, PWideChar(s), '', MB_OK);
end; 

但是,使用 UTF-8,您可以使用本机 RTL 完成相同的事情,但您仍然不能使用 ShowMessage()(好吧,您可以,但它不会显示非 ASCII字符正确):

var
  s : UTF8String;
begin
  s := UTF8Encode('This is my original string (y)');
  s := AnsiReplaceStr(s, '(y)', UTF8Encode(''));
  MessageBoxW(0, PWideChar(UTF8Decode(s)), '', MB_OK);
end;

无论哪种方式,请确保您的代码编辑器设置为以 UTF-8 格式保存 .pas 文件,否则您不能使用文字 '',您将不得不使用更多的东西像这样:

var
  Emoji: WideString;

SetLength(Emoji, 2);
Emoji[1] := WideChar($D83D);
Emoji[2] := WideChar($DC4D);

那么你可以这样做:

var s: WideString;
...
s := WideReplaceStr(s, '(y)', Emoji);

或:

var s: UTF8String;
...
s := AnsiReplaceStr(s, '(y)', UTF8Encode(Emoji));