Question

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?

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top