【发布时间】:2022-01-19 20:04:51
【问题描述】:
有没有机会在没有窗口的情况下拨打GetFontUnicodeRanges?例如,它可能是不允许与桌面交互的 Windows 服务。
目前我正在使用控制台应用程序对此进行测试:
program UnicodeConsoleOutput;
{$APPTYPE CONSOLE}
uses
SysUtils,
Windows;
var
NumWritten: DWORD;
Text: WideString;
u8s: UTF8String;
procedure Add(AStart, AEnd: Word);
var
i: Word;
begin
Text := Text + WideFormat('[%x...%x]:'#13#10, [AStart, AEnd]);
for i := AStart to AEnd do
Text := Text + WideChar(i);
Text := Text + WideString(#13#10#13#10);
end;
//Actually I want to get glyph ranges for "Consolas" font
procedure GetFontRanges();
type
TRangesArray = array[0..(MaxInt div SizeOf(TWCRange)) - 1] of TWCRange;
PRangesArray = ^TRangesArray;
const
ConsoleTitle = '{A46DD332-0D57-4310-B91E-A68957C20429}';
var
GS: PGlyphSet;
GSSize: LongWord;
i: Integer;
rng: TWCRange;
hConsole: HWND;
hDev: HDC;
begin
//A dirty hack to get console window handle suggested by Microsoft
SetConsoleTitle(PChar(ConsoleTitle));
hConsole := FindWindow(nil, PChar(ConsoleTitle));
hDev := GetDC(hConsole);
try
GSSize := GetFontUnicodeRanges(hDev, nil);
GetMem(Pointer(GS), GSSize);
try
GS.cbThis := GSSize;
GS.flAccel := 0;
GS.cGlyphsSupported := 0;
GS.cRanges := 0;
if GetFontUnicodeRanges(hDev, GS) <> 0 then begin
for i := 0 to GS.cRanges - 1 do begin
rng := PRangesArray(@GS.ranges)[i];
Add(Word(rng.wcLow), Word(rng.wcLow) + rng.cGlyphs - 1);
end;
end;
finally
FreeMem(Pointer(GS), GSSize);
end;
finally
ReleaseDC(hConsole, hDev);
end;
end;
begin
try
GetFontRanges();
SetConsoleOutputCP(CP_UTF8);
u8s := UTF8Encode(Text);
WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), PChar(u8s), Length(u8s),
NumWritten, nil);
except
on E: Exception do
Writeln(E.ClassName, ': ', E.Message);
end;
ReadLn;
end.
【问题讨论】:
-
有 Python 实用程序可以解析并提供有关 otf(以及 ttf)字体的信息。 (显然还有一个 unicode range 函数。但它在 python 中。
-
对不起,这里是 WinAPI 和 Delphi。你的评论完全断章取义。我在问具体的 WinAPI 功能。
-
那是相当古老的技术。您可以通过 API 没有将调用线程的最后一个错误设置为失败这一事实来判断。据推测,您需要传递 DC 的唯一原因是因为这就是您告诉 API 使用哪种字体的方式。在这种情况下,可能只需
CreateDC一个并选择您的字体。或者,使用更现代的 API。 DirectWrite 可能有你要找的东西。 -
附带说明,您可以使用
GetConsoleWindow(),而不是使用SetConsoleTitle()+FindWindow()。 -
@IInspectable "API 没有设置调用线程失败时的最后一个错误" - 大多数 GDI 函数没有。
标签: winapi unicode fonts delphi-6