gpt4 book ai didi

delphi - WinAPI : GetFontUnicodeRanges - I do not understand the result

转载 作者:行者123 更新时间:2023-12-03 15:25:20 25 4
gpt4 key购买 nike

我正在尝试获取 Unicode 字体字形范围(Delphi 6):

var GS:PGlyphSet;
GSSize:LongWord;
rng:TWCRange;
begin
GSSize := GetFontUnicodeRanges(Canvas.Handle, nil);
GetMem(Pointer(GS), GSSize);
try
GS.cbThis:=GSSize;
GS.flAccel:=0;
GS.cGlyphsSupported:=0;
GS.cRanges:=0;
if GetFontUnicodeRanges(Canvas.Handle, GS)<>0 then begin
for i:=0 to GS.cRanges-1 do begin
rng := GS.ranges[i];

奇怪的是,Length(GS.ranges) 是 1,但 GS.cRanges 是 309,当我尝试访问第二个范围 GS.ranges[1] 当然,我得到了范围检查错误。在我开启范围检查之前,它以某种神奇的方式发挥了作用。

引用类型(来自 Windows 模块):

PWCRange = ^TWCRange;
{$EXTERNALSYM tagWCRANGE}
tagWCRANGE = packed record
wcLow: WCHAR;
cGlyphs: SHORT;
end;
TWCRange = tagWCRANGE;

PGlyphSet = ^TGlyphSet;
{$EXTERNALSYM tagGLYPHSET}
tagGLYPHSET = packed record
cbThis: DWORD;
flAccel: DWORD;
cGlyphsSupported: DWORD;
cRanges: DWORD;
ranges: array[0..0] of TWCRange;
end;
TGlyphSet = tagGLYPHSET;

最佳答案

该结构利用了所谓的结构黑客:

ranges 成员是一个可变长度数组,内联放置在结构中。但实际上您无法将其编码为静态 C 类型。这就是为什么您调用该函数来找出要分配多少内存,然后在堆上分配该结构。如果您在堆栈上分配它,或者使用 SizeOf(...) 那么该结构会太小。

最简单的方法是禁用访问范围的代码的范围检查。尽管类型声明表示只有 0ranges 的有效索引,但实际上 0..cRanges-1 是有效的。

如果您不想禁用相关代码的范围检查,则采用元素 0 的指针,然后在循环中使用指针算术。

var
rng: PWCRange;
....
rng := @GS.ranges[0];
for i:=0 to GS.cRanges-1 do begin
// use rng^
inc(rng);
end;

在我看来,这是编写顺序访问代码的最简洁的方法。对于随机访问,并且范围检查有效,您将不得不声明一些额外的类型来击败范围检查:

type 
TWCRangeArray = array [0..(MaxInt div SizeOf(TWCRange))-1] of TWCRange;
PWCRangeArray = ^TWCRangeArray;

然后使用类型转换来访问各个元素:

rng := PWCRangeArray(@GS.ranges)[i];

关于delphi - WinAPI : GetFontUnicodeRanges - I do not understand the result,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18651998/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com