Our company upgraded to Delphi 12 a few months ago.
Today I discovered that my image viewer's context menu, which used to look like in the left image below, now appears with a single menu item blanked out (right image below):
Similarly, in a different app, I discovered that a pen icon was missing from some list box captions:
The code snippets responsible for these two strings are
FmiZoomOut.Caption := 'Zoom out'#9'−'; // U+2212: MINUS SIGN
and
Item.Caption := FInbox[Item.Index].Name +
IfThen(not FInbox[Item.Index].Note.IsEmpty, #32#32#32'✏');
respectively.
The problem appears to be caused by some string literals of the form #nn'x'
where x is a non-ASCII Unicode character. You can easily reproduce this in a new VCL app with the code
ShowMessage('Snowman:'#32'☃');
in the form's OnCreate
handler, for example.
What is causing this, and – more importantly – is there any workaround?
This certainly appears to be a bug introduced in Delphi 12.
Consider the following code:
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32'!';
ShowMessage(S); // breakpoint here
end;
In memory, this looks correct:
This is a six-character constant string literal containing the expected characters.
However,
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32'☃';
ShowMessage(S);
end;
produces a clearly incorrect string heap object:
This starts off correctly with reference count FF FF FF FF and length 6, but then the actual contents of the string are entirely off.
Clearly, this is a compiler (or possibly RTL) bug.
Likely, the consumer of this string will see the NUL character at the beginning and think that the string ends there. This explains the empty string shown in the message box.
Fortunately, the work around is almost trivial: Replace #nn'x'
with #nn + 'x'
.
procedure TForm1.FormCreate(Sender: TObject);
begin
var S := 'Test'#32 + '☃';
ShowMessage(S);
end;