我们公司几个月前升级到了Delphi 12。
今天我发现我的图像查看器的上下文菜单(以前看起来像下面的左图所示)现在显示为空白的单个菜单项(下面的右图):
同样,在另一个应用程序中,我发现某些列表框标题中缺少钢笔图标:
负责这两个字符串的代码片段是
FmiZoomOut.Caption := 'Zoom out'#9'−'; // U+2212: MINUS SIGN
和
Item.Caption := FInbox[Item.Index].Name +
IfThen(not FInbox[Item.Index].Note.IsEmpty, #32#32#32'✏');
分别。
该问题似乎是由某些
#nn'x'
形式的字符串文字引起的,其中 x 是非 ASCII Unicode 字符。您可以使用代码在新的 VCL 应用程序中轻松重现此内容
ShowMessage('Snowman:'#32'☃');
例如,在表单的
OnCreate
处理程序中。
造成这种情况的原因是什么,更重要的是,有什么解决方法吗?
这肯定是 Delphi 12 中引入的错误。
考虑以下代码:
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32'!';
ShowMessage(S); // breakpoint here
end;
在记忆中,这看起来是正确的:
这是一个包含预期字符的六字符常量字符串文字。
但是,
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32'☃';
ShowMessage(S);
end;
产生明显不正确的字符串堆对象:
这从引用计数 FF FF FF FF 和长度 6 开始正确,但随后字符串的实际内容完全关闭。
显然,这是一个编译器(或可能是 RTL)错误。
很可能,该字符串的使用者会在开头看到 NUL 字符,并认为该字符串到此结束。这解释了消息框中显示的空字符串。
幸运的是,解决方法几乎微不足道:将
#nn'x'
替换为 #nn + 'x'
。
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32 + '☃';
ShowMessage(S);
end;