2016-11-30 32 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 = ""; 
    }