0

I have a WindowsForm application that has a FlowLayoutPanel container with a TextBox inside. This control is bigger than the flow panel, I've set the flow panel to AutoScroll = true.

The problem is I don't know how to make the flow panel scroll to the position of the text edition. If I write continuously in the textbox eventually I pass beyond of what it is visible. The scroll remains at the top and I can't see what it is written.

In consequence the question is, how can I make the container react to keep visible what it is being written?

Nate B.
  • 942
  • 11
  • 31
mjsr
  • 7,410
  • 18
  • 57
  • 83
  • TextBox does not provide a decent way to notify you about caret position changes, there is no event for it. The sane way to go about it is to get Muhammad to go to the mountain, TextBox can display a scrollbar as well. – Hans Passant May 07 '14 at 18:42
  • Mmm sad to hear that but I can't give up to the idea so quickly. The whole thing contemplate that the textbox show all if its content, the height grows dynamically. What I'm trying now is to obtain the position of the caret and move the container scroll to ensure that it is visible....Till the moment I didn't succeed – mjsr May 07 '14 at 20:21
  • Screenshot? Question is why do you use `FlowLayoutPanel` at all. Shouldn't it be a normal `Panel`? And if so, then @HansPassant comment is right - let `TextBox` to show scrollbar and you are done. – Sinatr May 26 '14 at 12:06
  • @Sinatr because the flowLayoutPanel is used as a container to new controls added in runtime. One of the controls is a textbox that by requirement need to show all of its content, not part of it (We don't want to have multiples nested scrollbars). The solution provided by Sachamora is what we need. – mjsr Jun 02 '14 at 15:05

2 Answers2

2

There is a hacky solution, but if there is nothing better you can try it. First, subscribe for a TextChanged event. Than, on text changed, check in which line is the caret, check what's the height of the line and scroll the flow layout panel to the position of the line.

The hacky bit is basically to get the height of the line. To do that you have to subtract Y coordinate of the second line from the Y coordinate of the first line.

So the code is:

private void textBox1_TextChanged(object sender, EventArgs e)
{
    int lineHeight = 0;
    if (textBox1.Lines.Count() > 1)
    {
        Point p1 = textBox1.GetPositionFromCharIndex(textBox1.GetFirstCharIndexFromLine(0));
        Point p2 = textBox1.GetPositionFromCharIndex(textBox1.GetFirstCharIndexFromLine(1));
        lineHeight = Math.Abs(p1.Y - p2.Y);
    }

    int lineIndex = textBox1.GetLineFromCharIndex(textBox1.SelectionStart);
    flowLayoutPanel1.AutoScrollPosition = new Point(0, lineIndex * lineHeight);
}
PiotrWolkowski
  • 8,408
  • 6
  • 48
  • 68
  • What exactly didn't work? Did you debug the event handler? Does it provide values for each variable? Also, in my case the way I created the layout was to place a `TextBox` in the `FlowLayoutPanel` and the height of the `TextBox` exceeds the height of the `FlowLayoutPanel`. Maybe your layout is constructed differently and you need adjust the data in the event handler to your solution. – PiotrWolkowski May 30 '14 at 08:15
  • what can I say, I have done all you said, it didn't work , at least not on vertical scrolling. – Sachamora May 30 '14 at 08:20
2

I think I finally did it:

public partial class Form1 : Form
{
    public Point InitialTextBoxLoc ;

    public Form1()
    {
        InitializeComponent();
        InitialTextBoxLoc = textBox1.Location;
    }

    private void textBox1_TextChanged(object sender, EventArgs e)
    {
        Point caretLocalLoc = textBox1.GetPositionFromCharIndex(textBox1.Text.Length-1);
        Point caretLoc = new Point(caretLocalLoc.X + InitialTextBoxLoc.X,
                                   caretLocalLoc.Y + InitialTextBoxLoc.Y);

        Point scrollLoc = flowLayoutPanel1.AutoScrollPosition;
        if (caretLoc.X >= flowLayoutPanel1.Size.Width-10)
        {
            scrollLoc.X = caretLoc.X;

        }

        if (caretLoc.Y >= flowLayoutPanel1.Size.Height-10)
        {
            scrollLoc.Y = caretLoc.Y;
        }

        flowLayoutPanel1.AutoScrollPosition = scrollLoc;

    }
}
Sachamora
  • 479
  • 2
  • 13
  • Good job, this is what I need. I'm going to add the handler to the KeyPress event to be able to move in the textbox with the arrow keys. – mjsr Jun 02 '14 at 15:07