2012-02-17 82 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;