【问题标题】:How do I write a Unicode string to the console screen buffer?如何将 Unicode 字符串写入控制台屏幕缓冲区?
【发布时间】:2012-04-14 07:40:07
【问题描述】:

给定句柄(此处为hStdOut)到标准输出设备,我使用以下2个过程从控制台应用程序写入任意字符串:

摘录:

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;

我的麻烦:

这个语句没有像我预期的那样正确呈现字符串:

SendLn('The harder they come...');

我的问题:

是否存在WriteFile 的“WideString”重载,或者我是否应该考虑使用另一个可识别 Unicode 的函数来访问控制台屏幕缓冲区?

【问题讨论】:

    标签: delphi winapi delphi-xe windows-console


    【解决方案1】:

    一个问题是您需要以 bytes 而不是 characters 来指定长度。所以使用ByteLength 而不是Length。目前您传入的len 是缓冲区字节大小的一半。

    我也认为您不应该对nNumberOfBytesToWritelpNumberOfBytesWritten 参数使用相同的变量。

    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;
    

    如果您的 stdout 期望 UTF-16 编码的文本,则上述内容很好。如果不是,并且它需要 ANSI 文本,那么您应该切换到 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;
    

    您需要发送到标准输出设备的确切内容取决于它所期望的文本编码,我不知道。

    最后,如果这是您正在写入的控制台,那么您应该简单地使用WriteConsole

    【讨论】:

    • 感谢您的回答。使用 ByteLength 解决了长度问题,但我仍然遇到麻烦:字符串的每个字符都使用额外的空格字符呈现。
    • @menjaraz 是的,那是因为我认为您的标准输出设备需要 ANSI。尝试答案中的第二段代码。关于您使用的输出设备类型,您是否有更多信息可以告诉我们。
    • WriteConsole 完全符合我的预期。谢谢。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多