2

I am working on a UserControl that contains a multiline TextBox.

When using my control, one will be able to set the text that will be displayed. The TextBox should then adapt its Height to make the text fit, the Width cannot change.

So here is the property that handles the text :

[Editor(typeof(MultilineStringEditor), typeof(UITypeEditor))]
public string TextToDisplay
{
    get
    {
        return internalTextBox.Text;
    }
    set
    {
        internalTextBox.Text = value;
        AdaptTextBoxSize();
    }
}

My first attempt was rather simple :

private void AdaptTextBoxSize()
{
    int nbLignes = internalTextBox.Lines.Length;
    float lineHeight = internalTextBox.Font.GetHeight();
    internalTextBox.Height = (int)((nbLignes) * lineHeight);
}

This did not work as it doesn't take into account spacing between two lines of text. So the more lines I have in the text, the more I get clipped.

So I tried this :

private void AdaptTextBoxSize()
{
    Size textSize = internalTextBox.GetPreferredSize(new Size(internalTextBox.Width, 0));
    internalTextBox.Height = textSize.Height;
}

This does work when all the lines in the textbox are shorter than the Width. But when one line is longer and should be clipped to the next line, GetPreferredSize() returns a larger width than the one I passed, and therefore the height is too small.

So I changed again and tried this one:

private void AdaptTextBoxSize()
{
    Size textSize = TextRenderer.MeasureText(
                                             internalTextBox.Text, 
                                             internalTextBox.Font, 
                                             new Size(internalTextBox.Width, 0), 
                                             TextFormatFlags.WordEllipsis
                                             );


    internalTextBox.Height = textSize.Height;
}

This time the returned Width is correct, as it does not exceed the one I passed, but the height is the same as the previous trial. So it doesn't work either. I tried different combinations for TextFormatFlags, but could not manage to find the winning one...

Is this a bug from the framework?

The real question here is, is there another thing I can try, or another to achieve what I want (i.e. auto-adapt the height when setting the TextToDisplay property)?

Keyur Ramoliya
  • 1,900
  • 2
  • 16
  • 17
Martin Verjans
  • 4,675
  • 1
  • 21
  • 48
  • What is the value of the `UseCompatibleTextRendering` property? [This](https://stackoverflow.com/a/6705023/4934172) might be related. – 41686d6564 stands w. Palestine Jul 04 '18 at 10:57
  • @AhmedAbdelhameed Well I tried with the solution in your link but still have the same problem. The values are slightly different but I still have a line that is cut out if one of my lines is too long. – Martin Verjans Jul 04 '18 at 11:59
  • Why are you using `TextFormatFlags.WordEllipsis`? Try [simpler solution](https://stackoverflow.com/a/8048509/1997232). Measure text is the right way (no need to put a whole story into question), it should work. I suggest you to post only code with measuring text attempt and screenshot with problem. *"the height is the same as the previous trial"* might be an interesting, but not really useful observation. – Sinatr Jul 04 '18 at 12:07
  • 1
    There are known problem with width : [here](https://stackoverflow.com/q/1087157/1997232), [here](https://stackoverflow.com/q/2116216/1997232). Try using `TextFormatFlags.WordBreak` (from [here](https://stackoverflow.com/a/8361685/1997232)), is result different? – Sinatr Jul 04 '18 at 12:16
  • @Sinatr I actually have no problem measuring width, but with measuring height. My width is fixed but the calculated height doesn't seem to be correct when a line is too long. I'll update my question – Martin Verjans Jul 04 '18 at 12:44

1 Answers1

2

TextBox.GetPositionFromCharIndex returns the pixel position of a character. Position here means top/left so we need to add one more line..

This seems to work here:

textBox.Height = textBox.GetPositionFromCharIndex(textBox4.Text.Length - 1).Y + lineHeight;

I get the line height like this:

int lineHeight = -1;
using (TextBox t = new TextBox() { Font = textBox.Font }) lineHeight = t.Height;

I set the Height instead of the ClientSize.Height, which is slightly wrong unless BorderStyle is None. You can change to textBox.ClientSize = new Size(textBox.ClientSize.Width, l + lh);

TaW
  • 53,122
  • 8
  • 69
  • 111