我用 Delphi 编写了一个 Windows 程序,它使用 GetCharWidth 和 Em-Square 在屏幕和打印机上非常精确地放置和换行文本。这对于 ANSI 文本非常有效,您只需要检索和计算 255 个字符的宽度,但是当您使用 65535 个字符的 Unicode 时它太慢了。必须创建 2 个宽度数组,一个用于正常,一个用于粗体,问题变得更糟。
//Setup a reference canvas for measuring purposes
RefDC := CreateCompatibleDC ( FCanvas.Handle ) ;
DPI := GetDeviceCaps ( RefDC , LOGPIXELSY ) ;
//find EmSquare
GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
EmSq := otm[0].otmEmSquare ;
//calc NORMAL char sizes
GetObject ( FCanvas.Font.Handle , SizeOf ( lf ) , @lf ) ;
lf.lfHeight := -EmSq ;
lf.lfWidth := 0 ;
lf.lfWeight := FW_NORMAL ;
hf := CreateFontIndirect ( lf ) ;
hold := SelectObject ( RefDC , hf ) ;
GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
for a := 0 to $FFFF do
fCharWidth[a] := nCharWidth[a]* PixelSize / EmSq ;
SelectObject ( RefDC , hold ) ;
DeleteObject ( hf ) ;
//calculate line height
PixelSize := abs ( fCanvas.Font.Size * DPI / 72 ) ;
GetOutlineTextMetrics ( RefDC , sizeof(otm) , @otm[0] ) ;
LineHt := round ( ( otm[0].otmTextMetrics.tmHeight +
otm[0].otmTextMetrics.tmExternalLeading ) *
PixelSize / EmSq ) ;
//calculate Bold char sizes
lf.lfWeight := FW_BOLD ;
hf := CreateFontIndirect ( lf ) ;
hold := SelectObject ( RefDC , hf ) ;
GetCharWidth ( RefDC , 0 , $FFFF , nCharWidth ) ;
for a := 0 to $FFFF do
fBoldWidth[a] := nCharWidth[a] * PixelSize / EmSq ;
SelectObject ( RefDC , hold ) ;
DeleteObject ( hf ) ;
DeleteDC ( RefDC ) ;`
最佳答案
计算单个字符的宽度并在 Unicode 中将它们相加不仅非常慢,而且是错误的并且无法正常工作。 Unicode 将字符标记组合在一起,有时以复杂的方式。
使用 Unicode,正确的做法是将整个字符串传递给 Windows API 函数 GetTextExtentExPoint连同你的线的宽度,它会计算出多少个字符适合你。
关于windows - 所见即所得与 Unicode,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3497471/