delphi – WinAPI:GetFontUnicodeRanges – 我不明白结果
我想获得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; 解决方法
这个结构使用了所谓的struct hack:
> http://c-faq.com/struct/structhack.html 范围成员是可变长度数组,内嵌在结构中.但是你无法在静态C类型中实际编码.这就是为什么你调用函数来找出要分配多少内存,然后堆分配结构.如果您在堆栈上分配它,或使用SizeOf(…),那么结构将太小. 最简单的方法是禁用访问范围的代码的范围检查.虽然类型声明说只有0是范围的有效索引,但事实上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]; (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |