2016-11-30 85 views
0

我想寫一個函數,需要繪製一個字符串的圖像。圖像有1-5個文本框,每個文本框都有一個x,y,寬度和高度。這些細節是在我解析的XML文件中定義的,所以我可以訪問每個盒子的這些細節。Graphics.DrawString到多個矩形

我的問題是我是否可以使用graphics.DrawString(或類似的)方法很容易地做到這一點。下面的示例函數將創建一個具有指定的x,y,寬度,高度的矩形,然後在其中繪製一個字符串。如果字符串不適合,它會截斷。

public void DrawStringRectangleFormat(Graphics g) 
    { 
     // Create string to draw. 
     String drawString = "Sample Text is too long to fit into this tiny lil rectangle area right here"; 

     // Create font and brush. 
     Font drawFont = new Font("Arial", 16); 
     SolidBrush drawBrush = new SolidBrush(Color.Black); 

     // Create rectangle for drawing. 
     float x = 150.0F; 
     float y = 150.0F; 
     float width = 200.0F; 
     float height = 50.0F; 
     RectangleF drawRect = new RectangleF(x, y, width, height); 

     // Set format of string. 
     StringFormat drawFormat = new StringFormat(); 
     drawFormat.Alignment = StringAlignment.Center; 

     // Draw string to screen. 
     g.DrawString(drawString, drawFont, drawBrush, drawRect, drawFormat); 
    } 

我想,而不是這是什麼,是不是截斷,它會停在最後裝配字,並進入下一個矩形(文本框)。這樣我可以使用所有可用的文本框。

有沒有一種方法可以做到這一點?否則,我將需要實現我自己的drawString方法。

+2

我想你會需要分割串入的話,請撥打['GraphicsMeasureString()'](https://msdn.microsoft.com/en-us/library/6xe5hazb %28v = vs.110%29.aspx?f = 255&MSPPError = -2147217396),並做到這一點很難。不*太*難,真的。給定一個元組列表{word,wordRect}',這是一個適合文本的簡單循環。 –

+2

我想你需要看'Graphics.MeasureCharacterRanges'來看看哪些單詞需要被截斷。該函數可用於計算字符串中字符組的字符串座標(例如每個字)。如果您嘗試對'Graphics.MeasureString'使用多個調用,那麼恐怕由於字距(kerning)而導致結果不夠精確。 – RogerN

回答

0

這就是我。它做我所描述的。感謝您的答案。

public void DrawStringInTextboxes(string text, Graphics g) 
    { 

     String drawString = text; 

     PrivateFontCollection fontCollection = new PrivateFontCollection(); 
     fontCollection.AddFontFile(System.Web.Hosting.HostingEnvironment.MapPath("~/Content/Fonts/Squidgingtons.ttf")); 
     var squidingtonsFontFamily = fontCollection.Families[0]; 
     Font squidingtons = new Font(squidingtonsFontFamily, textParameters[0].MaxFontSize); 
     Font drawFont = new Font("Arial", 60); 
     SolidBrush drawBrush = new SolidBrush(Color.Black); 

     StringFormat drawFormat = new StringFormat(); 
     drawFormat.Alignment = StringAlignment.Center; 

     char[] delimiterChars = { ' ' }; 
     string[] words = drawString.Split(delimiterChars); 
     string finalString = ""; 
     int textBoxIndex = 0; 

     foreach (string word in words) 
     { 
      //set the dimensions for the first textbox and create a rectangle with those specifications. 
      float x = textParameters[textBoxIndex].Left; 
      float y = textParameters[textBoxIndex].Top; 
      float width = textParameters[textBoxIndex].Width; 
      float height = textParameters[textBoxIndex].Height; 
      RectangleF Rect = new RectangleF(x, y, width, height); 
      //if the current finalString + the next word fits in the current box, add the word to finalString. 
      if (g.MeasureString(finalString + word + " ", squidingtons).Width < textParameters[textBoxIndex].Width) 
      {  
       finalString = finalString + " " + word; 
       //if this is the last word, print the finalString and we are done. 
       if (word == words[words.Length - 1]) 
       { 
        g.DrawString(finalString, squidingtons, drawBrush, Rect, drawFormat); 
        break; 
       } 

      } 
      //the current finalString + next word did not fit in the box. Draw what we have to the first box. 
      else { 
       g.DrawString(finalString, squidingtons, drawBrush, Rect, drawFormat); 
       //Hold onto the word that didnt fit. It will be the first word of the next box. 
       finalString = word; 
       if (textBoxIndex +1 >= textParameters.Length) 
       { 
        //if we are out of textboxes, we are done. 
        break; 
       } 
       else 
       { 
        //move on to the next textbox. The loop begins again with new specifications set for the textbox. 
        textBoxIndex++; 
       } 
      } 

     } 
     squidingtons.Dispose(); 
     drawBrush.Dispose(); 
     drawFont.Dispose(); 
    } 
1

OK,你所要做的就是通過字符串中的每個字符循環,並連接到一個最終的字符串.. 所以基本上的foreach(MyString中的字符C)... 然後使用measurestring什麼,你檢查查看該字符串是在盒子的長度,如果是,開始下RECT ...

https://msdn.microsoft.com/en-us/library/6xe5hazb(v=vs.110).aspx

+0

如果你需要一個代碼示例,我可以把東西掀起來,我只是在工作中的一個項目中,所以我很懶惰。 – Trey

+0

我會嘗試一下,併發布我的解決方案,如果它的作品,或要求從你的樣本。謝謝 – Jaked222

+0

隨時隨地,我愛圖形!祝你有美好的一天。 – Trey

1

該解決方案使用StringFormat的設置,以確保每次調用的DrawString僅繪製適合的話。然後,Graphics.MeasureCharacterRanges計算不適合矩形的單詞,其餘文本溢出到下一個佈局矩形。

您可能需要自定義輸入字符串如何拆分爲單詞。現在我只是將它分開在空白的邊界。

using System.Text.RegularExpressions; 
using System.Drawing; 

/// <summary> 
/// Draw a string using one or more layout rectangles. Words which don't fit will overflow into the next layout rectangle. 
/// </summary> 
private static void DrawOverflowString(Graphics graphics, string drawString, RectangleF[] layoutRectangles, StringAlignment alignment) 
{ 
    var drawFont = new Font("Arial", 16.0f); 
    var black = new SolidBrush(Color.Black); 
    var format = new StringFormat() 
    { 
     Alignment = alignment, 
     Trimming = StringTrimming.Word, 
     FormatFlags = StringFormatFlags.LineLimit 
    }; 
    var wordRegex = new Regex("[^\\s]+"); 
    string remainingText = drawString; 
    foreach (var layoutRect in layoutRectangles) 
    { 
     // Draw everything that will fit into this text box 
     graphics.DrawString(remainingText, drawFont, black, layoutRect, format); 

     // calculate which words did not fit 
     var wordMatches = wordRegex.Matches(remainingText); 
     var ranges = wordMatches.OfType<Match>().Select(x => new CharacterRange(x.Index, x.Length)).ToArray(); 
     format.SetMeasurableCharacterRanges(ranges); 
     var wordRegions = graphics.MeasureCharacterRanges(remainingText, drawFont, layoutRect, format); 

     var allfit = true; 
     for (int i = 0; i < wordRegions.Length; i++) 
     { 
      if (wordRegions[i].GetBounds(graphics).Width == 0.0f) 
      { 
       allfit = false; 
       remainingText = remainingText.Substring(wordMatches[i].Index); 
       break; 
      } 
     } 

     if (allfit) 
      break; 
    } 

    drawFont.Dispose(); 
    black.Dispose(); 
} 
1
 protected override void OnPaint(PaintEventArgs e) 
    { 
     // Call the OnPaint method of the base class. 
     base.OnPaint(e); 
     List<Rectanglestring> testrecs = new List<Rectanglestring>(); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 12, 40, 12), whattodraw = "" }); 
     testrecs.Add(new Rectanglestring {targetrect= new Rectangle(0, 25, 35, 12),whattodraw="" }); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 35, 35, 12), whattodraw = "" }); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 45, 35, 12), whattodraw = "" }); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 65, 35, 12), whattodraw = "" }); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 85, 35, 12), whattodraw = "" }); 
     testrecs.Add(new Rectanglestring { targetrect = new Rectangle(0, 95, 55, 12), whattodraw = "" }); 
     string mystringtofit = "This is just an example"; 

     foreach (Rectanglestring rect in testrecs) 
     { 
      for (int i = 0; i < mystringtofit.Length; i++) 
      { 
       if (mystringtofit[i] == ' ' && rect.whattodraw.Length > 0) break; 
       if (mystringtofit[i] == ' ') continue; 
       string teststring = rect.whattodraw + mystringtofit[i]; 
       SizeF stringSize = stringSize = e.Graphics.MeasureString(teststring, new Font("Ariel", 12)); 
       if (stringSize.Width >= rect.targetrect.Width) break; 
       rect.whattodraw += mystringtofit[i]; 


      } 

      mystringtofit = mystringtofit.Substring(rect.whattodraw.Length); 
      if (mystringtofit.StartsWith(" ")) 
      { 
       mystringtofit = mystringtofit.Substring(1); 
      } 
      e.Graphics.DrawString(rect.whattodraw, Font, new SolidBrush(ForeColor), rect.targetrect); 
     } 
     // Call methods of the System.Drawing.Graphics object. 

    } 
    public class Rectanglestring 
    { 
     public Rectangle targetrect = new Rectangle(); 
     public string whattodraw = ""; 
    }