2012-02-17 66 views
5

我想计算给定字符串的公制单位的准确文本宽度。我的伪代码如下所示:准确计算公制单位的文本宽度

Bitmap.Canvas.Assign(Font); 
PixelWidth := Bitmap.Canvas.TextWidth(Font) 
MetricWidth := PtToMM * (PixelWidth * 72.0/GetScreenDPI); 

PtToMM是被定义为0.352777778常数。这对于某些字体和字体大小非常精确,但对于其他字体太小或太大。我尝试了很多其他可能性,如GetCharWidth32GetCharABCWidths,映射模式MM_LOMETRIC,但我只是无法让它工作。这个问题困扰着我,所以请任何人帮忙,告诉我我错在哪里。非常感谢你!

编辑我检查了一个字符串:度量宽度计算为4.17厘米,实际打印输出(在纸张上测量)的宽度为4.4厘米(字体Times New Roman,尺寸12)。

+2

一些问题:您如何知道计算出的文本宽度不是它应该是的?你是否使用正确的DC来获取文字宽度? (即:你有可能在屏幕画布上阅读,然后在打印画布上使用结果?)。我从来没有使用这种计算来获得实际的METRIC值,但PIXEL值始终是准确的。我使用类似的代码在连续纸上使用点阵式打印机打印1米长的表格,其中列宽根据文本内容计算。 – 2012-02-17 11:14:46

+0

@Comsin:不知道我得到你的问题。我使用它来进行打印预览和打印,所以它在屏幕和打印机上均可使用。 – jpfollenius 2012-02-17 11:27:59

+1

这听起来像你试图比Windows更聪明。你不应该自己计算它,你应该让你的打印机设备上下文告诉你纸张的宽度是多少? – 2012-02-17 14:11:01

回答

0

我没有广泛地测试它,但它似乎给出了正确的结果。结果是文本的宽度在千分之一毫米。此功能不支持包装和其他特殊的考虑。

此外,请注意,使用打印机时,不正确的打印注册可以“拉伸”文本。

此外,请注意,对于打印机,例如,将打印分辨率从300 ppp更改为1200 ppp也会更改结果。

uses 
    ConvUtils, stdConvs ; 

function CalcRequiredTextWidth(aDC : HDC; aFont : TFont; const asText: string): Double; 
var vCanvas : TCanvas; 
    iPixelsWidth : Integer; 
    dInchWidth : Double; 
    iFontSize : Integer; 
begin 
    vCanvas := TCanvas.Create; 
    try 
    vCanvas.Handle := aDC; 

    vCanvas.Font.Assign(aFont); 
    iFontSize := vCanvas.Font.Size; 
    vCanvas.Font.PixelsPerInch := GetDeviceCaps(aDC, LOGPIXELSY); 
    vCanvas.Font.Size := iFontSize; 

    iPixelsWidth := vCanvas.TextExtent(asText).cx; 

    dInchWidth := iPixelsWidth/GetDeviceCaps(vCanvas.Handle, LOGPIXELSX); 

    Result := Convert(dInchWidth, duInches, duMicrons); 

    finally 
    vCanvas.Free; 
    end; 
end;