如何在Delphi的Memo控件中实现Unicode文本装饰

4
我是一个有用的助手,可以为您翻译文本。
我有一个小的Delphi 10.3.3 应用程序,其中包含一些文本编辑功能,使用TMemo让用户输入文本。
我正在尝试包括一些格式选项,就像这个网站提供的一样:

http://qaz.wtf/u/convert.cgi?text=How%20do%20it%20on%20Delphi

当我从上面的网站复制“环绕”的文本并粘贴到备忘录中时,它起作用,显示为“环绕”。但我希望能够在我的应用程序中让用户应用格式。
例如,我想要一个速度按钮来将“圆形”格式应用于当前选定的TMemo文本:用户选择文本,单击此速度按钮,然后所选文本获得“环绕”格式。

enter image description here


VCL备忘录不支持格式化。您需要一个RTF编辑控件。 - David Heffernan
@DavidHeffernan 如果我从上面的网站复制格式化文本,它会显示在备忘录上,那么它怎么可能不支持呢? - delphirules
1
@David:你知道这与格式无关吗?这完全是关于用另一个字符替换一个字符。 - Andreas Rejbrand
显然我误解了你想要做的事情。 - David Heffernan
@DavidHeffernan 没关系,无论如何都感谢你的帮助。 - delphirules
1个回答

4
这相当容易。如果您查看带圈字母数字的Unicode图表,您会意识到以下映射是有效的:
function EncircleChr(AChr: Char): Char;
begin
  case AChr of
    '0':
      Result := Chr($24EA);
    '1'..'9':
      Result := Chr($2460 + Ord(AChr) - Ord('1'));
    'a'..'z':
      Result := Chr($24D0 + Ord(AChr) - Ord('a'));
    'A'..'Z':
      Result := Chr($24B6 + Ord(AChr) - Ord('A'));
  else
    Result := AChr;
  end;
end;

因此,使用
function Encircle(const S: string): string;
var
  i: Integer;
begin
  SetLength(Result, S.Length);
  for i := 1 to S.Length do
    Result[i] := EncircleChr(S[i]);
end;

并且

procedure TForm1.Button1Click(Sender: TObject);
begin
  Memo1.SelText := Encircle(Memo1.SelText);
end;

你可以获得所需的行为:

一个TMemo的截图,其中字母和数字被转换为它们的环绕版本。


1
@delphirules:太好了!当然,您也可以对其他类型的装饰进行相同的操作。 - Andreas Rejbrand
好的,我会做到的!再次感谢,祝你周末愉快! - delphirules
我正在尝试对其他装饰采用相同的方法,但不知何故它不起作用。例如,我正在尝试应用负圆圈并在此处获取代码:https://www.compart.com/en/unicode/search?q=negative#characters。它适用于具有4位数字的代码(如$278A),但不适用于具有5位数字的代码(如$1F150);在这种情况下,会出现奇怪的字符。你知道为什么吗? :) - delphirules
2
@delphirules:Delphi的字符类型宽度为两个字节(=四个十六进制数字),因此它仅支持BMP。个人而言,我尽量避免使用BMP之外的字符,因为它们不太容易处理。此外,很少有字体包含BMP之外字符的字形... - Andreas Rejbrand
我明白了,谢谢您提供的信息!我可以通过创建一个包含所有负数的向量,并手动将其映射到结果来解决这个问题。 - delphirules
5
一个超出BMP的字符由两个Delphi字符(代理对)表示。因此,您需要一个Delphi字符串来表示这样一个字符。您可以通过执行例如Char.ConvertFromUtf32($1F17F)来获取这样的字符串。 - Andreas Rejbrand

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接