2016-11-30 5 views
0

Я пытаюсь написать функцию, которая должна нарисовать строку для изображения. Изображение имеет от 1 до 5 текстовых полей, каждый из которых имеет x, y, ширину и высоту. Эти данные определены в XML-файле, который я обрабатываю, поэтому у меня есть доступ к ним для каждого окна.Graphics.DrawString для нескольких прямоугольников

Мой вопрос заключается в том, могу ли я использовать графический инструмент.DrawString (или аналогичный), чтобы сделать это легко. Функция примера ниже создаст прямоугольник с указанными x, y, width, height, а затем нарисует строку внутри. Если строка не подходит, она обрезается.

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», я боюсь, что результаты не будут достаточно точными из-за кернинга. – 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

Хорошо, что вы должны сделать, это цикл по каждому полукокса в строке, и конкатенация до конечной строки .. поэтому в основном Еогеасп (символ с в группе MyString) ... затем с помощью MeasureString, вы проверяете см, если строка по длине ящика, если он есть, начинается на следующий прямоугольнику ...

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

+0

Если вам нужен пример кода, я могу что-то взбить, я просто посередине проекта на работе, поэтому я немного ленив. – Trey

+0

Я попробую это и отправлю свое решение, если оно работает, или попросите от вас образец. Спасибо – Jaked222

+0

В любое время, я люблю графику! Хорошего дня. – Trey

1

Это решение использует параметры StringFormat «s, чтобы гарантировать, что каждый вызов DrawString рисует только те слова, которые подходят. Затем вычисляет слова, которые не помещаются в прямоугольник, а оставшийся текст переполняется в следующий прямоугольник макета.

Возможно, вам потребуется настроить, как входная строка разбивается на слова. Прямо сейчас я просто разделяю его на безымянных границах.

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 = ""; 
    } 
Смежные вопросы