2014-02-21 20 views
4

我有一個自定義的WinForms控件,它可以被描述爲某種終端控件(比如包含Putty的控件)。據此,控件應顯示大量字符,每個字符都具有不同的顏色和背景顏色(最差情況)。向WinForms控件繪製大量的單個字符

目前我使用(種類過時的)Graphics.MeasureString方法來確定固定大小字體中單個字符的大小,以便我可以計算特定行和列中字符的位置。然後我使用Graphics.DrawString來繪製字符。爲了優化性能,我創建了一個BufferedGraphics,並使用它們的屬性創建組字符,只需調用一個DrawString即可繪製具有相同顏色的連續字符。 (因爲每個字符一個DrawString呼叫是真的慢。)

現在的問題是,DrawString顯然計算從MeasureString稍微不同的一個字符的寬度。當我一次繪製一條完整的線時,結果的文本寬度與我使用單個字符的寬度乘以線的字符數所計算的寬度不同。這只是一個或兩個像素(或者更少),但您可以清楚地看到它 - 尤其是因爲我使用的是反鋸齒,因此您甚至可以看到差異僅爲半個像素。

以下示例代碼在窗體的圖形上繪製了一個長字符串a,後面跟着字符'B'。然後它通過測量a計算出的位置只畫一個'B'

var f = new Form { 
    Width = 1200, 
    Height = 500, 
    Font = new Font("Consolas", 11, FontStyle.Regular) 
}; 

f.Paint += delegate(object sender, PaintEventArgs e) { 
    var a = "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"; 
    var size = e.Graphics.MeasureString(a, f.Font, new PointF(0, 0), StringFormat.GenericTypographic); 

    using (var black = new SolidBrush(Color.Black)) 
    { 
     e.Graphics.DrawString(a + "B", f.Font, black, 0, 0, StringFormat.GenericTypographic); 
     e.Graphics.DrawString("B", f.Font, black, size.Width, 20, StringFormat.GenericTypographic); 
    } 
}; 

f.Show(); 

而且如果你仔細觀察,你會看到第二個B是約一個像素更正確的 - 至少我的顯示設置(100%dpi的規模,啓用ClearType的)。儘管一個像素並不多,但當您使用Unicode字符U+2500U+257F繪製線條時,如果字符未完全對齊,它看起來非常難看。

我也不能使用TextRenderer類,因爲它的MeasureString方法返回整數值,但當然DrawString不會在全像素位置繪製每個字符(你會被要求用排計算出的位置對齊/列和測量的整數字符大小)。

所以我的問題是:是否有任何(高效率)的方法來繪製字符串完全對齊到他們使用字符大小計算相應的位置?


P.S:MeasureString有200個字符的字符串返回正好200倍的MeasureString返回值與單字符串。

+0

只是一個快速的猜測:嘗試在每個地方顯式使用Single/SizeF/PointF/RectangleF,我記得這解決了一個問題我有一個地方(令我非常驚訝).. – KekuSemau

+0

不幸的是,我已經在使用'float's到處。當我使用'TextRenderer'類時,我用'int'試過了。那時差距甚至更大。 – fero

回答

0

我在測量圖形中的字符串時遇到了一些類似的問題。我已經使用SizeInPoints,Font類中的一個屬性,並將其乘以字符串中的字符數...我不知道它是否有幫助。 如果不是,它可能是像素的「舍入」問題...然後我會嘗試放大字體大小(可能是10倍),測量它,然後再用10除以大小來爲背景着色。 我希望它有幫助。 祝你好運!問候!

0

我有同樣的問題。

看來,行爲取決於字體大小。

用以下代碼更改字體後,此問題未發生。

Font = new Font("Consolas", 20.0F, FontStyle.Regular, GraphicsUnit.Pixel) 

但是,在下面的另一個字體大小仍然會發生此問題。

Font = new Font("Consolas", 20.3F, FontStyle.Regular, GraphicsUnit.Pixel) 

我對這個問題的背景猜測:MeasureString和束帶使用不同的佈局常規,他們在四捨五入的浮點數誤差不同的特點。只有'簡單'字體大小他們給出相同的結果。

此外,位圖字體未出現此問題。

相關問題