我有一個自定義的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+2500
到U+257F
繪製線條時,如果字符未完全對齊,它看起來非常難看。
我也不能使用TextRenderer
類,因爲它的MeasureString
方法返回整數值,但當然DrawString
不會在全像素位置繪製每個字符(你會被要求用排計算出的位置對齊/列和測量的整數字符大小)。
所以我的問題是:是否有任何(高效率)的方法來繪製字符串完全對齊到他們使用字符大小計算相應的位置?
P.S:MeasureString
有200個字符的字符串返回正好200倍的MeasureString
返回值與單字符串。
只是一個快速的猜測:嘗試在每個地方顯式使用Single/SizeF/PointF/RectangleF,我記得這解決了一個問題我有一個地方(令我非常驚訝).. – KekuSemau
不幸的是,我已經在使用'float's到處。當我使用'TextRenderer'類時,我用'int'試過了。那時差距甚至更大。 – fero