tags:

views:

45

answers:

2

In a WinForms TextBox control, how can I obtain, in screen coordinates the bounding box of the text as a specified character position? I know the start index and end index of the text in question, but given those two values, how can I find the bounding box of that text?

To be clear... I know how to get the bounding box of the control itself. I need the bounding box of a substring of the TextBox.Text.

A: 

Perhaps, you can use Graphics.MeasureString. You can get graphics object for form using CreateGraphics method. Let's say, you have to find bounding box for "World" in "Hello World". So first measure "Hello " string - that would give you width of "Hello " that in turn will tell you left position. Then measure actual word to get right position.

VinayC
A: 

I played around with Graphics.MeasureString but couldn't get accurate results. The following code gives me fairly consistent results at different font sizes with Graphics.MeasureCharacterRanges.

private Rectangle GetTextBounds(TextBox textBox, int startPosition, int length)
{
  using (Graphics g = textBox.CreateGraphics())
  {
    g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.AntiAlias;

    CharacterRange[] characterRanges = { new CharacterRange(startPosition, length) };
    StringFormat stringFormat = new StringFormat(StringFormat.GenericTypographic);
    stringFormat.SetMeasurableCharacterRanges(characterRanges);

    Region region = g.MeasureCharacterRanges(textBox.Text, textBox.Font,
                                             textBox.Bounds, stringFormat)[0];
    Rectangle bounds = Rectangle.Round(region.GetBounds(g));

    Point textOffset = textBox.GetPositionFromCharIndex(0);

    return new Rectangle(textBox.Margin.Left + bounds.Left + textOffset.X,
                         textBox.Margin.Top + textBox.Location.Y + textOffset.Y,
                         bounds.Width, bounds.Height);
  }
}

This snippet just places a panel on top of my TextBox to illustrate the computed rectangle.

...
Rectangle r = GetTextBounds(textBox1, 2, 10);
Panel panel = new Panel
{
  Bounds = r,
  BorderStyle = BorderStyle.FixedSingle,
};

this.Controls.Add(panel);
panel.Show();
panel.BringToFront();
...
MattP
Wow Matt... that's awesome. Thanks!!
Damion