Laden...

Auomatische Anpassung der TextBox-Größe funktioniert nicht

Erstellt von Palladin007 vor 11 Jahren Letzter Beitrag vor 10 Jahren 3.566 Views
Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren
Auomatische Anpassung der TextBox-Größe funktioniert nicht

Ich habe hier folgenden Bestandteil einer Form:

        private void textBox1_TextChanged(object sender, EventArgs e)
        {
            SizeF size = this.CreateGraphics().MeasureString(textBox1.Text, textBox1.Font);

            // Höhe und Breite erfassen
            int width = (int)size.Width;
            int height = (int)size.Height;

            // Anpassen an MaximumSize
            if (width > textBox1.MaximumSize.Width) width = textBox1.MaximumSize.Width;
            if (height > textBox1.MaximumSize.Height) height = textBox1.MaximumSize.Height;

            // Anpassen an MinimumSize
            if (width < textBox1.MinimumSize.Width) width = textBox1.MinimumSize.Width;
            if (height < textBox1.MinimumSize.Height) height = textBox1.MinimumSize.Height;

            // Neue Größe speichern
            this.textBox1.Width = width;
            this.textBox1.Height = height;
        }

Und diese Eigenschaften:

            this.textBox1.WordWrap = true;
            this.textBox1.Multiline = true;
            this.textBox1.Margin = new Padding(0);
            this.textBox1.MaximumSize = new Size(600, 1000);
            this.FormBorderStyle = FormBorderStyle.None;

Das soll bewirken, dass die TextBox sich automatisch an seinen Inhalt anpasst, aber noch im Rahmen der Maximal- und Minimal-Vorgaben bleibt.

Wenn ich das nun starte, funktioniert das mit der Breite auch wunderbar, bis die maximale Breite erreicht ist, aber dann wird keine neue Zeile begonnen.
Zumindest sehe ich das nicht, weil die TextBox sich nicht nach unten aus dehnt.

Ich denke, das liegt daran, dass in "size" die Breite und Höhe des Textes angegeben wird, aber wenn der Text immer auf einer Zeile liegt, wird auch immer die Höhe gleich bleiben.
Habs mit "textBox1.Lines.Length" aber da bleibt die Anzahl Zeilen ja auch gleich.

Hat jemand eine Idee, wie ich es hin bekommen kann, dass sich der TextBox immer eine Zeile anfügt, wenn der Text zu lang für die vorherige wird?

Oder muss ich da mit der RichTextBox arbeiten?

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

771 Beiträge seit 2009
vor 11 Jahren

Du kannst der MeasureString-Methode noch die maximale Breite als 3. Parameter angeben.

Palladin007 Themenstarter:in
2.079 Beiträge seit 2012
vor 11 Jahren

Super, funktioniert^^

Danke 😃

NuGet Packages im Code auslesen
lock Alternative für async/await

Beim CleanCode zählen nicht die Regeln, sondern dass wir uns mit diesen Regeln befassen, selbst wenn wir sie nicht befolgen - hoffentlich nach reiflichen Überlegungen.

L
14 Beiträge seit 2013
vor 10 Jahren

Hi Zusammen

Ich habe ein kleines Problem zum selben Thema. Vielleicht kann einer von euch mir helfen, auch wenn das Thema vom letzten Jahr ist.

Ausgangspunt ist, das ich gewisse Multiline-Textboxen auf einer Form habe, die leider nicht sehr viel Platz haben, weil die Form nur von Steuerelementen überladen ist (typisch Kunde: am besten alles auf einen Blick ^^)
Um jetzt den gesamten Text der Textbox anzeigen zu können, soll sich die Größe der Textbox an dessen Inhalt anpassen, sobald der Fokus auf dieser Textbox liegt. Dabei soll jedoch die Breite der Textbox unverändert bleiben und nur die Höhe angepast werden. Eine MaximumSize gibt es nicht. Nur die MinimumSize, die der Größe er Textbox im nichtfokusiierten Zustand entspricht. (Diesen Wert speichere ich beim laden der Form jeweils im Tag der Textbox)

Gebe ich nun Text ein, erweitert sich diese auch schön brav um die Zeilen. Verlasse ich die Textbox geht sie in den Ausgangzustand zurück. Jedoch ist mir beim Testen etwas aufgefallen. Nach mehrerem Einfügen von Absätzen passiert es ab und zu das sich die Höhe des Textfeldes nicht ändert sondern die oberste Zeile hochgeschoben wird, sodass man sie nicht sieht. Das ist ja eigentlich unerwünscht, da man den gesamten Text sehen möchte, soweit es die Größe des Bildschirmes zulässt.

Woran liegt das? Kann man das eventuell verhindern?

LG


        private void txt_changed(object sender, EventArgs e)
        {
             //Größe eventuell aktualisieren
             if ((pan_doc.Controls.Contains(sender as TextBox)) && (sender as TextBox).Focused)
                createNewSize(sender);  
        }

        private void textbox_Enter(object sender, EventArgs e)
        {
            //Control hat focus -> Größe der Textbox an Text anpassen
            if ((pan_doc.Controls.Contains(sender as TextBox)) && (sender as TextBox).Focused)
            {
                //Berechnen der neuen Größe
                createNewSize(sender);
            }
        }

        private void createNewSize(object sender)
        {
            SizeF test = this.CreateGraphics().MeasureString((sender as TextBox).Text, 
                                        (sender as TextBox).Font, (sender as TextBox).Size.Width);
            (sender as TextBox).Height = (int)test.Height + 1;
            (sender as TextBox).BringToFront();
        }

        private void Textbox_Leave(object sender, EventArgs e)
        {
            if (pan_doc.Controls.Contains(sender as TextBox))
            {//Größe zurücksetzen
                (sender as TextBox).Size = (Size)(sender as TextBox).Tag;
            }
        }

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo LearningGirl,

ich würde es als erstes mal mit Width-x bei MeasureString probieren, wobei x empirisch zu ermitteln wäre.

herbivore

L
14 Beiträge seit 2013
vor 10 Jahren

Guten Morgen herbivore,

danke für die schnelle Antwort. Ich verstehe nur gerade nicht, was du mit deiner Aussage andeuten willst. Was meinst du mit diesem x?

LG

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo LearningGirl,

ich ich schon sagte, wäre x ein Wert (eine Konstante), den man empirisch ermitteln müsste. Beginne bei 1, und erhöhe jedes Mal um 1, sollte der Fehler noch auftreten.

herbivore

4.221 Beiträge seit 2005
vor 10 Jahren

Offtopic:

Du kannst den Speicherbedarf noch optimieren.... wenn Du das Graphics nach Verwendung disposed...


using (Graphics g=this.CreateGraphics(.......)
{

}

Früher war ich unentschlossen, heute bin ich mir da nicht mehr so sicher...

L
14 Beiträge seit 2013
vor 10 Jahren

@herbivore
Jetzt verstehe ich... werde mich gleich mal an die Arbeit machen.

@Programmierhans
Danke für den Tipp 😉

L
14 Beiträge seit 2013
vor 10 Jahren

Also ich hatte nun etwas experimentiert mit dem wisth - x. Jedoch hat das nicht verbessert.

Außerdem ist mir aufgefallen dass die Methode anscheinend die Absätze (\r\n) nicht richtig interpretiert. steht der Absatz als letztes da, schiebt er den text immer außer Sicht. Steht dahinter ein Text, interpretiert er es richtig, aber nur wenn es unmittelbar dahinter steht. bei mehreren Zeilen scheint er aber auch ab und zu eine Außnahme zu machen...

Beispiel:
ich kürze jeden Absatz (\r\n) mal mit einem * ab

Text -> Ergebnis

[...]** -> Fehlt 1 Zeile
[...]* -> Fehlt 1
[...]f -> richtig dargestellt
[...]f -> Fehlt 1
[...]fm -> richtig
[...]fm
-> Fehlt 1
[...]fm** -> Fehlt 1
[...]fmg -> richtig
[...]fm
g* -> Fehlt 1
[...]fmg -> Fehlt 1
[...]fmg* -> Fehlt 1
[...]fmgm -> richtig
[...]fmg
m-> Fehlt 1
[...]fmg
m-> Fehlt 1
[...]fm
gm-> Fehlt 2
[...]fmgm**m-> Fehlt 1
usw.

Mal fehlt unten eine Zeile, mal schiebt er den Text nach oben.

49.485 Beiträge seit 2005
vor 10 Jahren

Hallo LearningGirl,

übergib mal Regex.Replace (textBox1.Text, @"[\r\n]+$", "\r\n.") an MeasureString. Das sollte das Problem bis auf den Fall "Fehlt 2" lösen. Der lässt sich aber vielleicht durch meinen ersten Vorschlag beheben.

herbivore

L
14 Beiträge seit 2013
vor 10 Jahren

Hi herbivore,

danke für deine Hilfe. Bei den ersten Versuchen haben sich Verbesserungen gezeigt, jedoch keine vollständige Lösung.
So ergab sich für die gleichen Tests wie oben folgende Verbesserungen.

[...]** -> Fehlt 1 Zeile
[...]* -> jetzt richtig
[...]f -> richtig
[...]f -> jetzt richtig
[...]fm -> richtig
[...]fm
-> jetzt richtig
[...]fm** -> Fehlt 1
[...]fmg -> richtig
[...]fm
g* -> jetzt richtig
[...]fmg -> Fehlt 1
[...]fmg* -> jetzt Fehlt 2
[...]fmgm -> richtig
[...]fmg
m-> jetzt richtig
[...]fmg
m-> Fehlt 1
[...]fm
gm-> Fehlt 2
[...]fmgm**m-> Fehlt 1

Wenn ich jedoch zum Beispiel nur Absätze einfüge, ohne Text dazwischen, dann schiebt er den Text bei jedem neuen Absatz eine Zeile weiter hoch und die Textbox nimmt an Höhe nicht zu. Erst wenn man dann ein Zecihen einfügt, korigiert er die Höhe mit einem Schub. Dabei fehlt ab und zu jedoch wieder eine Zeile.

Die ersten Tests mit width - x waren auch nicht erfolgreicher.

LG

4.938 Beiträge seit 2008
vor 10 Jahren

Hallo LearningGirl,

du solltest mal textBox.ClientSize.Width verwenden (daher auch der Vorschlag von herbivore bzgl. "-x").
Und dann schau dir mal die Überladung von MeasureString() mittels StringFormat an und probiere mal verschiedene Einstellungen durch, besonders die FormatFlags.
Notfalls würde ich einfach die TextBox in der Höhe ein bißchen größer machen, damit der Text immer reinpaßt.

L
14 Beiträge seit 2013
vor 10 Jahren

Hi Th69,

ich habe eben eine andere Variante mal versucht und die sieht sehr vielversprechend aus. Die Höhe scheint immer den richtigen Wert zu haben. Nur ab und zu ist beim Aktualisieren der Höhe ein Flackern zu verzeichnen, wenn man zu schnell zu viel verändert:


        private void createNewSize(object sender)
        {
            Size sz = new Size((sender as TextBox).ClientSize.Width, int.MaxValue);
            TextFormatFlags flags = TextFormatFlags.WordBreak;
            int padding = 3;
            int borders = (sender as TextBox).Height - (sender as TextBox).ClientSize.Height;
            sz = TextRenderer.MeasureText((sender as TextBox).Text, (sender as TextBox).Font, sz, flags);
            int h = sz.Height + borders + padding;
            if ((sender as TextBox).Top + h > this.ClientSize.Height - 10)
            {
                h = this.ClientSize.Height - 10 - (sender as TextBox).Top;
            }
            (sender as TextBox).Height = h;
            (sender as TextBox).BringToFront();
        }