delphi - 如何设置控制台字体?

标签 delphi delphi-xe6

如何为控制台设置 unicode 字体?我尝试了以下操作,但在 GetCurrentConsoleFontEx 行上收到了 AV。

program ConsoleVsUnicode;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils;

type
  COORD = record
    X, Y: smallint;
  end;

  TCONSOLE_FONT_INFOEX = record
    cbSize: cardinal;
    nFont: longword;
    dwFontSize: COORD;
    FontFamily: cardinal;
    FontWeight: cardinal;
    FaceName: array [0 .. LF_FACESIZE - 1] of WideChar;
  end;

  PCONSOLE_FONT_INFOEX = ^TCONSOLE_FONT_INFOEX;

function SetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL; ConsoleInfo: PCONSOLE_FONT_INFOEX): BOOL; external kernel32 name 'SetCurrentConsoleFontEx';
function GetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL; ConsoleInfo: PCONSOLE_FONT_INFOEX): BOOL; external kernel32 name 'GetCurrentConsoleFontEx';

procedure SetConsoleFont(const AFontSize: word);
var
  ci: TCONSOLE_FONT_INFOEX;
  ch: THandle;
begin
  if NOT CheckWin32Version(6, 0) then
  EXIT;

  FillChar(ci, SizeOf(TCONSOLE_FONT_INFOEX), 0);
  ci.cbSize := SizeOf(TCONSOLE_FONT_INFOEX);

  ch := GetStdHandle(STD_OUTPUT_HANDLE);
  GetCurrentConsoleFontEx(ch, FALSE, @ci); // AV Here!

  ci.FontFamily := FF_DONTCARE;
  // ci.FaceName:= 'Lucida Console';
  ci.FaceName := 'Consolas';
  ci.dwFontSize.X := 0;
  ci.dwFontSize.Y := AFontSize;
  ci.FontWeight := FW_BOLD;
  SetCurrentConsoleFontEx(ch, FALSE, @ci);

end;

begin
  SetConsoleFont(32);
  ReadLn;

end.

最佳答案

这些函数使用stdcall调用约定。您需要添加他们的声明。

function SetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL;
  ConsoleInfo: PCONSOLE_FONT_INFOEX): BOOL; stdcall;
  external kernel32 name 'SetCurrentConsoleFontEx';
function GetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL;
  ConsoleInfo: PCONSOLE_FONT_INFOEX): BOOL; stdcall;
  external kernel32 name 'GetCurrentConsoleFontEx';

您还应该检查这些 API 调用的返回值。例如,使用 Win32Check 就合适。

顺便说一句,调用 CheckWin32Version 是没有意义的。如果您导入的 API 函数不存在于 kernel32.dll 中,则该程序甚至不会加载。如果您确实需要 XP 支持,您可以使用延迟加载来解决这个问题并支持 XP。

最后一点是,这些函数的结构参数不是可选的。在这种情况下,转换为 constvar 会使函数调用更加方便。

function SetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL;
  const ConsoleInfo: TCONSOLE_FONT_INFOEX): BOOL; stdcall;
  external kernel32 name 'SetCurrentConsoleFontEx';
function GetCurrentConsoleFontEx(ConsoleOutput: THandle; MaximumWindow: BOOL;
  var ConsoleInfo: TCONSOLE_FONT_INFOEX): BOOL; stdcall;
  external kernel32 name 'GetCurrentConsoleFontEx';
<小时/>

您将面临的一个更根本的问题是Delphi 的控制台输出函数不支持Unicode。更改字体不会改变这一点。当您调用 Write 时,Delphi 无法处理 Unicode 文本。

要从 Delphi 输出 Unicode 文本,您需要直接访问 Windows 控制台 API。例如,WriteConsoleW

即使这样也无法帮助您处理需要代理对的字符,例如中文文本。控制台 API 仍然仅限于 UCS2,因此如果您的文本具有代理项对,那么您就运气不好了。

<小时/>

更新

根据TOndrej's answer to another question ,您可以通过以下方式从 Write 生成 Unicode 输出:

  1. 使用 SetConsoleOutputCP(CP_UTF8) 将控制台代码页设置为 UTF-8,并且
  2. 使用 UTF8Encode 将 UTF-8 编码的 8 位文本传递给 Write

但是,我相信您仍然无法克服对 BMP 之外的文本缺乏 UTF-16 代理对支持的问题。

关于delphi - 如何设置控制台字体?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24762413/

相关文章:

delphi - 如何创建复合控件?

c++ - 在 Windows 中获取已安装的 Mini Filter 驱动程序列表

delphi - 无法在 win64 模式下运行新项目,但 win32 模式运行正常

德尔福XE6 "Error reading form"

delphi - 如何在Delphi中的Units初始化部分捕获异常

delphi - 计算最大字体大小

delphi - TTimer.OnTimer 事件处理程序是可重入的吗?

delphi - 无法加载 SSL 库 - 找不到 dll

delphi - 无效的类型转换

delphi - 鼠标悬停(类似提示)delphi