Laden...

[gelöst] Nach maximaler Anzahl Zeichen in einer RichTextBox Zeilenumbruch einfügen

Erstellt von schorge vor 7 Jahren Letzter Beitrag vor 7 Jahren 4.486 Views
S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren
[gelöst] Nach maximaler Anzahl Zeichen in einer RichTextBox Zeilenumbruch einfügen

**9.06.15 GELÖST
Falls Interesse besteht wie man eine richTextBox dann auf eine
PDF bekommt, kann ich gerne weiterhelfen.

Der Vorteil ist, genau die breite und Absätze wie in der RichTextBox
gesehen werden, sind auch auf der PDF-Seite so dargestellt.**

Moinsen,

ich such nun schon etwas länger an einer Lösung beim schreiben
in eine RichTextBox nach einem Einstellbarem MaxChar automatisch
eine neue Zeile hinzuzufügen. Auf der Suche bei Google
hat keine Lösung funktioniert.

Ich komme hier irgendwie durcheinander und dreh mich im Kreis 🤔 :


 private void rtb1_TextChanged(object sender, EventArgs e)
        {
            List<string> wrapedText = new List<string>();
            wrapedText = WordWrap(rtb1.Text, 30);
            string linedText = "";
            foreach (string lineText in wrapedText)
            {
                linedText += lineText;
            }
            rtb1.Text = linedText;
        }

        public static List<string> WordWrap(string input, int maxCharacters)
        {
            List<string> lines = new List<string>();

            if (!input.Contains(" ") && !input.Contains("\n"))
            {
                int start = 0;
                while (start < input.Length)
                {
                    lines.Add(input.Substring(start, Math.Min(maxCharacters, input.Length - start)));
                    start += maxCharacters;
                }
            }
            else
            {
                string[] paragraphs = input.Split('\n');

                foreach (string paragraph in paragraphs)
                {
                    string[] words = paragraph.Split(' ');

                    string line = "";
                    foreach (string word in words)
                    {
                        if ((line + word).Length > maxCharacters)
                        {
                            lines.Add(line.Trim());
                            line = "";
                        }

                        line += string.Format("{0} ", word);
                    }

                    if (line.Length > 0)
                    {
                        lines.Add(line.Trim());
                    }
                }
            }
            return lines;
        }

sobald ich einen Buchstabe eingebe, ist ja der Cursor wieder vorne,
vielen Dank schon mal für Hilfe.

Hinweis von Coffeebean vor 7 Jahren

Ich hab die rote Farbe mal entfernt. Dies sieht eher nach einer Ermahnung von Moderatoren als nach einer Hilfe aus.

16.842 Beiträge seit 2008
vor 7 Jahren

Manchmal helfen Code-Kommentare, dass man selbst versteht, was man macht.

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Sorry:


 private void rtb1_TextChanged(object sender, EventArgs e)
        {
            RichTextBox txbe = (sender as RichTextBox);

            int loc = txbe.SelectionStart;
            // die Cursor Location

            List<string> wrapedText = new List<string>();
            wrapedText = WordWrap(rtb1.Text, 30);
            // der bei leerzeichen geteilte Text aus der rtb

            string linedText = "";
            // der neue Text, getrennt für den späteren Print

            foreach (string lineText in wrapedText)
            {
                linedText += lineText + Environment.NewLine;
                // ein Absatz nach jeder Zeile
            }
            
            rtb1.Text = linedText;
            // der fertige Text ausgeben
            txbe.Text.Replace('$', '%');

            txbe.SelectionStart = loc;
            // der Cursor zum Ende der rtb (richTextBox)

            
        }

        /// <summary>
        /// wandelt einen string nach einer bestimmten anzahl von Zeichen in eine List (mehrere Zeilen) um
        /// </summary>
        /// <param name="input">Der zu verwendente String</param>
        /// <param name="maxCharacters">Maximale Zeichen pro Zeile</param>
        /// <returns></returns>
        public static List<string> WordWrap(string input, int maxCharacters)
        {
            List<string> lines = new List<string>();

            if (!input.Contains(" ") && !input.Contains("\n"))
            {
                int start = 0;
                while (start < input.Length)
                {
                    lines.Add(input.Substring(start, Math.Min(maxCharacters, input.Length - start)));
                    start += maxCharacters;
                }
            }
            else
            {
                string[] paragraphs = input.Split('\n');

                foreach (string paragraph in paragraphs)
                {
                    string[] words = paragraph.Split(' ');

                    string line = "";
                    foreach (string word in words)
                    {
                        if ((line + word).Length > maxCharacters)
                        {
                            lines.Add(line.Trim());
                            line = "";
                        }

                        line += string.Format("{0} ", word);
                    }

                    if (line.Length > 0)
                    {
                        lines.Add(line.Trim());
                    }
                }
            }
            return lines;
        }

Ich habe hier eben das noch gefunden, weis aber nicht wie ich es mit dem TextChangedEvent verbinden kann...

5.299 Beiträge seit 2008
vor 7 Jahren

Wozu ist das eiglich gut?
Bei mir hat Richtextbox den ZeilenUmbruch bereits eingebaut.

Und generell ist das höchst problematisch, bei jeder Text-Änderung den Text ganz neu wieder zusammenzusetzen (was ja selbst wieder eine Text-Änderung ist).
mal abgesehen davon, dass dann der Cursor neu zu positionieren ist - Was passiert da eiglich, wenn der User ein Wort markiert und löscht - oder mit Ctr-V ein paar Worte einfügt?

Der frühe Apfel fängt den Wurm.

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Also Zeilenumbruch gibt es ja, ich will ihn aber automatisch bei einem WordWrap also am Control-Ende oder aber auch nach einer gewissen länge haben.

Das ist ja mein Problem, ich will nicht immer den ganzen Text zusammensetzen
weis mir aber keinen Rat wie ich das realisiere...

3.003 Beiträge seit 2006
vor 7 Jahren

Also Zeilenumbruch gibt es ja, ich will ihn aber automatisch bei einem WordWrap also am Control-Ende oder aber auch nach einer gewissen länge haben.

Okay, JETZT bin ich auch verwirrt. Nach meinem Verständnis macht WordWrap genau das, was du da schreibst. Also noch einmal: was willst du erreichen?

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

1.029 Beiträge seit 2010
vor 7 Jahren

Hi,

kann es sein, dass du eigentlich was drucken möchtest und du dafür irgendwelche Zeilenumbrüche haben möchtest? Oder was genau willst du damit erreichen?

Denn die RichTextBox kann das in der Tat alles - und als Anwender wäre ich ehrlich gesagt fuchsig, wenn mir irgendein Programmierer meine Eingabe auf solche Art verändert, weil das vollkommen gegen jede Konvention geht harte Zeilenumbrüche in einen Text zu zaubern, der eigentlich nur ein WordWrap machen soll.

LG

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Nach "new" hätte ich hier gerne den Zeilenumbruch:


"{\\rtf1\\ansi\\ansicpg1252\\deff0\\deflang1031{\\fonttbl{\\f0\\fnil\\fcharset0 Microsoft Sans Serif;}}\r\n\\viewkind4\\uc1\\pard\\f0\\fs44 Am Ende hier soll ein new Line kommen \\fs17\\par\r\n}\r\n"

Erst nach "ENTER" kommt ein Zeilenumbruch.

@Taipi88:
Es wird zum Drucken übergeben, soll aber
in einer Spalte nur die breite der RichTextBox haben.
Der Anwender sieht also in der RichTextBox schon die
breite die auch ausgedruckt wird.

3.003 Beiträge seit 2006
vor 7 Jahren

Ah. Völlig anderes Szenario.

Überlass der Textbox das Word-Wrapping, das kann sie besser als du 😉. Sobald gedruckt werden soll, übernimmst du die Zeilen der Textbox so, wie sie zu dem Zeitpunkt umbrochen sind, und fügst am Ende pro Zeile einen Zeilenumbruch hinzu (für den Drucker).

Zeilenweises auslesen der Textbox ist beispielsweise hier besprochen (erste Antwort).

LaTino
EDIT: Typo
EDIT: so, habs ausprobiert. Windows-Form, schmale Richtextbox, button, breite Textbox. Text in die RichTextBox eingeben, und dann per Button-Klick:


private void button1_Click(object sender, EventArgs e)
{
    int lineCount = richTextBox1.GetLineFromCharIndex(richTextBox1.Text.Length);
    textBox1.Text = string.Join(Environment.NewLine, Enumerable.Range(0, lineCount+1).Select(
        lineIndex =>
            {
                int start = richTextBox1.GetFirstCharIndexFromLine(lineIndex);
                int end = lineIndex < lineCount ? richTextBox1.GetFirstCharIndexFromLine(lineIndex + 1) : richTextBox1.TextLength;
                return richTextBox1.Text.Substring(start, end - start);
            }));
}

...übernimmt den Text aus der schmalen RichTextbox in die breite TextBox, aber mit den Umbrüchen aus der RichTextBox.

Hth 😃.

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

F
10.010 Beiträge seit 2004
vor 7 Jahren

Ich wüsste nicht mal warum ich mir das ganze überhaupt antun sollte, da man die RTB auch selber zum Drucken bringen kann.

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Ist in meinem Fall so, das ich den RichTextBox Text
in einer DB speicher.

Beim Drucken laden aus der DB, Parse den rtf-Text in eine pdf-Datei,
wo ich dann nur die Umrücke \n\t habe um ordentlich zu drucken
und leider nicht die

LaTino hat mich aber auf eine Idee gebracht,
das ich jetzt mal versuche den rtf-Text vor dem speichern
in die DB neu schreibe.

Bei LaTino's Tip geht leider die Formatierung verlorgen,
da ich ja nur den Text habe, ich habe den rtf-String ändern muss...

3.003 Beiträge seit 2006
vor 7 Jahren

Bei LaTino's Tip geht leider die Formatierung verlorgen,
da ich ja nur den Text habe, ich habe den rtf-String ändern muss...

Versuch's mal über die Rtf-Property der RichTextBox. Wird ggf etwas schwieriger, den Index im RTF zu finden, der dem gefundenen Index im reinen Text entspricht (an der Stelle, wo der Zeilenumbruch hin soll).

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Also habe es nun geschafft die Formatierung zu behalten, bitte um Verbesserungsvorschläge!

(- 9.6.15 kleine Anpassungen


   /// <summary>
        /// Gibt eine RichTextBox aus mit WordWrap absätzen und gleibleibentem Style
        /// </summary>
        /// <param name="rtbIn">RichTextBox</param>
        /// <returns></returns>

  private RichTextBox wordWrapRtf(RichTextBox rtbIn)
        {
            RichTextBox rtbOut = new RichTextBox();           
            //rtbOut bekommt den Text mit Style von rtbIn übergeben, zusätzlich werden die
           // WordWrap Umbrüche am Ende RichTextBox eingefügt

            int lineCount = rtbIn.GetLineFromCharIndex(rtbIn.Text.Length);
            bool neuerAbsatz = false;
            bool absatzErstellt = true;

            for (int i = 0; i < lineCount + 1; i++)
            {
                int start = rtbIn.GetFirstCharIndexFromLine(i);
                int end = i < lineCount ? rtbIn.GetFirstCharIndexFromLine(i + 1) : rtbIn.TextLength;
                                
                if (absatzErstellt)
                {
                    neuerAbsatz = false;
                }
                else
                {
                    neuerAbsatz = true;
                }
                for (int rChar = start; rChar < end; rChar++)
                {
                    string toAppend = rtbIn.Text[rChar].ToString();

                    if (toAppend == "\n")
                    {
                        absatzErstellt = true;
                        rtbOut.AppendText(Environment.NewLine);
                    }
                    else 
                    {
                        
                        if (neuerAbsatz)
                        {
                            rtbOut.AppendText(Environment.NewLine);
                            rtbOut.AppendText(toAppend);
                            neuerAbsatz = false;
                        }
                        else
                        {
                            absatzErstellt = false;
                            rtbOut.AppendText(toAppend);
                        }
                        rtbOut.Select(rtbOut.TextLength - 1, 1);
                        rtbIn.Select(rChar, 1);

                        rtbOut.SelectionAlignment = rtbIn.SelectionAlignment;
                        rtbOut.SelectionBullet = rtbIn.SelectionBullet;
                        rtbOut.SelectionColor = rtbIn.SelectionColor;
                        rtbOut.SelectionFont = rtbIn.SelectionFont;
                        rtbOut.SelectionHangingIndent = rtbIn.SelectionHangingIndent;
                        rtbOut.SelectionIndent = rtbIn.SelectionIndent;
                        rtbOut.SelectionCharOffset = rtbIn.SelectionCharOffset;
                    }                   
                }
            }
            return  rtbOut;
        }

463 Beiträge seit 2009
vor 7 Jahren

Also Name in der Art button1_Click(.....) oder **richTextBox1 **oder **button1 **finde ich persönlich immer suboptimal...
Zum anderen ist mir nicht klar, was du mit rtbout machst, denn diese ist mit Verlassen des Events nicht mehr verfügbar... oder kommt da eigentlich noch mehr im Event und du hast nur einen Teil gepostet?

3.003 Beiträge seit 2006
vor 7 Jahren

Zum anderen ist mir nicht klar, was du mit rtbout machst, denn diese ist mit Verlassen des Events nicht mehr verfügbar... oder kommt da eigentlich noch mehr im Event und du hast nur einen Teil gepostet?

Er benutzt die Instanz als Helferobjekt. Sie wird nach Beendigung der Methode nicht mehr benötigt.

LaTino

"Furlow, is it always about money?"
"Is there anything else? I mean, how much sex can you have?"
"Don't know. I haven't maxed out yet."
(Furlow & Crichton, Farscape)

1.040 Beiträge seit 2007
vor 7 Jahren

Falls Interesse besteht wie man eine richTextBox dann auf eine
PDF bekommt, kann ich gerne weiterhelfen.**){red}

Kannst du die Lösung bitte hier posten? Nach x Jahren erreicht man in der Regel viele User nicht mehr per PN. Danke. =)

S
schorge Themenstarter:in
129 Beiträge seit 2014
vor 7 Jahren

Da ich selber viel von meinem Eigenen Programm eingebunden habe,
muss ich da erst ein "verständliches" Snippet von erstellen,
aber ich werde es dann demnächst hier mal posten.