2012-08-07 19 views
2

我開發一個像Word一樣的程序。爲此,我需要將字符串寫入相同的「行」,並且我還希望能夠以不同方式格式化每個單詞/字母/句子,控制顏色,大小,字體等。用於圖形的C#字符串長度

所以我必須計算像素字符串的長度和高度,以便將它們排成一行。但是函數(Graphics) MeasureString有個問題,這個函數會在字符串後面添加額外的長度。這個功能也有一些空白問題。

我嘗試了不同的StringFormater,但每次它們返回太多的長度或不夠。

函數是否存在在Graphics對象上寫入不同的格式化字符串或函數來計算字符串的精確像素長度?

+1

查看方法「remarks」@ http://msdn.microsoft.com/en-us/library/6xe5hazb.aspx - 它解釋了額外的間距(懸垂的字形)和注意到'MeasureCharacterRanges'是什麼用於精確的佈局計算。 – 2012-08-07 10:49:08

+0

謝謝,它的作品。 – 2012-08-07 11:10:54

回答

4

首先,這是一個相當棘手的問題得到妥善解決 - 你可能會更好試圖找到一個現有的控制(例如,RichTextBox),解決了這個要求。

這就是說,如果你確實想這樣做,那麼這或多或少是解決這個問題的正確方法,但是如果你看看MSDN documentation,你會注意到你看到的行爲是故意的

MeasureString方法設計用於使用與各個串 ,並且包括之前和字符串 後的額外的空間少量以允許懸垂字形。此外,DrawString方法會調整 字形點以優化顯示質量,並可能會顯示比MeasureString報告的字符串更窄的字符串 。爲了獲得合適的 爲相鄰串中的佈局的度量(例如,實施 格式化文本時),則使用MeasureCharacterRanges方法或的 MeasureString方法,需要一個一個StringFormat,並傳遞 GenericTypographic。另外,請確保TextRenderingHintGraphicsAntiAlias

所以它聽起來像你對我應該改爲使用Graphics.MeasureCharacterRanges Method代替。

這是我準備的一個樣本,它處理呈現兩種不同顏色的文本。嘗試一下,將其粘貼到一個新的形式

protected override void OnPaint(PaintEventArgs e) 
{ 
    // This is where we wish to print our string 
    var region = new RectangleF(50, 50, 200, 50); 

    // This is the font we wish to use 
    var font = new Font("Times New Roman", 16.0F); 

    // Draw a string for comparison 
    DrawString(e.Graphics, "RedBlack", font, Brushes.Black, new RectangleF(50, 150, 200, 50)); 

    // Draw the first string and keep a track of the Region it was rendered in 
    var first = DrawString(e.Graphics, "Red", font, Brushes.Red, region); 

    // Adjust the region we wish to print 
    region = new RectangleF(region.X + first.GetBounds(e.Graphics).Width, region.Y, region.Width, region.Height); 

    // Draw the second string 
    DrawString(e.Graphics, "Black", font, Brushes.Black, region); 

    base.OnPaint(e); 
} 

private Region DrawString(Graphics g, string s, Font font, Brush brush, RectangleF layoutRectangle) 
{ 
    var format = new StringFormat(); 
    format.SetMeasurableCharacterRanges(new[] { new CharacterRange(0, s.Length) }); 

    g.DrawString(s, font, brush, layoutRectangle, format); 
    return g.MeasureCharacterRanges(s, font, layoutRectangle, format)[0]; 
} 

這是什麼樣子

screenshot of form

請注意,你需要小心剪裁 - GDI將「打包」呈現的文本在你新的生產線在默認情況下,但是這不會工作了,你最終會像這樣的東西

screenshot of form with incorrect line wrapping

此外,如果您嘗試打印出不同字體/字體大小的文本,那麼這些字體的「底部」將不會排列在您期望的位置。試着看看Formatting text on a common baseline關於如何處理這個問題的一些提示。

+0

謝謝,它的工作原理。 – 2012-08-07 11:34:40