How do I write a Unicode string to the console screen buffer?
-
28-05-2021 - |
Pregunta
Given a handle (hStdOut here) to the standard output device, I use the following 2 procedures to write an arbitrary string from a console application:
Excerpt:
procedure Send(const s: string);
var
len: cardinal;
begin
len:=Length(s);
WriteFile(hStdOut,s[1],len,len,nil);
end;
procedure SendLn(const s: string);
begin
Send(s + #13#10);
end;
My trouble:
This statement doesn't render correctely the string as I expected:
SendLn('The harder they come...');
My Question:
Is there a "WideString" overload of WriteFile
or should I consider another Unicode-aware function that access the console screen buffer?
Solución
One problem is that you need to specify the length in bytes rather than characters. So use ByteLength
rather than Length
. At the moment what you are passing in len
is half the byte size of the buffer.
I also believe that you should not use the same variable for the nNumberOfBytesToWrite
and lpNumberOfBytesWritten
parameters.
procedure Send(const s: string);
var
NumberOfBytesToWrite, NumberOfBytesWritten: DWORD;
begin
NumberOfBytesToWrite := ByteLength(s);
if NumberOfBytesToWrite>0 then
WriteFile(hStdOut, s[1], NumberOfBytesToWrite, NumberOfBytesWritten, nil);
end;
The above is fine if your stdout
is expecting UTF-16 encoded text. If not, and if it is expecting ANSI text then you should switch to AnsiString.
procedure Send(const s: AnsiString);
var
NumberOfBytesToWrite, NumberOfBytesWritten: DWORD;
begin
NumberOfBytesToWrite := ByteLength(s);
if NumberOfBytesToWrite>0 then
WriteFile(hStdOut, s[1], NumberOfBytesToWrite, NumberOfBytesWritten, nil);
end;
Exactly what you need to send to the standard output device depends on what text encoding it is expecting and I don't know that.
Finally, if this is a console that you are writing to then you should simply use WriteConsole
.