RichTextBox -- I am sooo Confused

T

Tom

Inserting text into a RichTextBox is a snap! >>

textBox1.Text += "Enter string 0000\n";
textBox1.Text += "Enter string 0001\n";
textBox1.Text += "Enter string 0002\n";
textBox1.Text += "Enter string 0003\n";

How do I then go back and programmatically remove let's say line #2?

As amazingly simple as this sounds ... I am equally dumbfounded by not
being able to find the solution. :(

Please shed some light on this for me.

Thanks!

-- Tom
 
N

Nicholas Paldino [.NET/C# MVP]

Tom,

You have to take the entire text string, parse it to identify the
elements that you don't want to include in the text, reconstruct the string,
and then set the Text property back to that string.
 
C

cfps.Christian

From what you've put in it looks more like you need a listbox rather
than a richtextbox. As far as deleting specific lines you would be
removing text from a gigantic string.
 
D

Dom

There's a few ways.

1. Remember that the "\n" can be found in the Text property. So you
can split the Text back into the original lines by using r.Text.Split
("\n", ...);
2. If possible, just rewrite the entire property without the string.

Dom
 
P

Peter Duniho

Inserting text into a RichTextBox is a snap! >>

textBox1.Text += "Enter string 0000\n";
textBox1.Text += "Enter string 0001\n";
textBox1.Text += "Enter string 0002\n";
textBox1.Text += "Enter string 0003\n";

How do I then go back and programmatically remove let's say line #2?

While the suggestions to process the Text property directly will work,
given what you're trying to do I think that accessing the text via the
Lines property would be easier. It basically does the String.Split() for
you, returning an array of strings, one per line. So:

void RemoveLine(TextBox box, int line)
{
string[] lines = box.Lines;

Array.Copy(lines, line + 1, lines, line, lines.Length - line - 1);
lines[lines.Length - 1] = null;
box.Lines = lines;
}

or something like that...my apologies if there's an off-by-one error. I
didn't actually compile or run the code. :)

Pete
 
T

Tom

Thanks Everybody !!

I had searched a few hours before posting and then soon stumbled into
the "TextBoxBase" category of methods. My search skills are pathetic!

The RTB must have some powerful controls buried deep within ... but
not enough examples on programmatically maneuvering within its buffer.

I long for a simplistic tool >>

textBox1.RemoveRange(int lineStart, int lineCount);

Just like in ArrayList ... but then things would be just too easy?

I've tried searching for the line feed with no success as of yet.

string findMe = "\n";
int indexToText = textBox1.Find(findMe, 0, RichTextBoxFinds.None);

The above does not work. I know those line feeds are not stripped out
because you can allow wrapping and then shrink the control to force
wrapping ... followed by expanding the control that returns the lines
to unwrapped. Being able to search for a >> chr(10), Char(10), '\n',
or however you properly specify a non printing character would be nice
considering "\n" does not work.

This work is part of a large data file viewer with small resource
usage project. I am trying to create this project for both future
usage and as a learning aid. I initiate the read at an arbitrary
location within the data file. Typically near the end of what are
often 50+ MB files.

My disk input is simple using this method >>

FileStream.Read(byte[] array, int offset, int count);

Then I trim the partial sentences away using a logic loop that
searches for byte(10). The front trimming is simply >>

int trim0 = 0;
while(byteArray[trim0] != 10) ++trim0;
long Position_0 = ++trim0;

Then I split the trimmed byteArray into lines and store them in an
ArrayList. This ArrayList is my buffer; however, it is a waste of
memory space!! There is no reason why the RTB could not be used as the
buffer storage space if adequate control was achieved.

As it is now ... I can clear the RTB and reconstruct it from the
ArrayList whenever I jump to another area of the data file. Good RTB
control would allow local scrolling to be much more efficient. I'd
really like the RTB caret to trigger buffer events. But learning about
that caret is another issue in itself.

This learning project of mine is certainly kickin me around. Someday I
will post it in its entirety and hopefully some other newbs can
benefit from it. Getting some guru level critique will be a very
humbling and educational event I look forward too.

Thanks again for all the comments!! Every suggestion and nudge gets me
that much closer to success. :)

-- Tom
 
P

Peter Duniho

Thanks Everybody !!

I had searched a few hours before posting and then soon stumbled into
the "TextBoxBase" category of methods. My search skills are pathetic!

For what it's worth: when you are looking at the documentation for a given
class on MSDN, you can click on the "Members" link, and that will take you
to a page with _all_ of the members of the class, including the inherited
ones. It's only in the navigation pane that only the members defined by
that actual type are listed.

Same thing if you click on the individual "Properties", "Methods",
"Constructor", etc. links.
The RTB must have some powerful controls buried deep within ... but
not enough examples on programmatically maneuvering within its buffer.

I long for a simplistic tool >>

textBox1.RemoveRange(int lineStart, int lineCount);

Just like in ArrayList ... but then things would be just too easy?

Have you looked at my reply? The other suggestions, frankly, did not
involve all that much work either. But using the Lines property gives you
direct, pre-parsed access to the lines in the text box. You originally
asked for the ability to remove just one line, so that's the example I
posted. But it would be simple to modify the code to remove a range of
lines.

Pete
 
T

Tom

Pete --

Your advice arrived while I was responding to earlier comments. I have
a major guilt issue here in that I over simplified my task in the hope
of learning more about the inner workings of the RichTextBox. (Not too
deep, I'm just learning!) In doing so I have cheated myself out of
receiving help at my project's structural level. I am essentially
splitting a byte array into lines and storing these lines in an
ArrayList. I then populate the RTB from the ArrayList.

I had to stress test this ArrayList - buffering logic repeatedly to
remove the off-by-one errors. I had a few in there ... but that part
is confirmed to be working! :)

And the bigger picture is I am building a viewer of large data files
that loads only the area of interest and does not hog memory
resources. Often my data files exceed 50 MB.

The ArrayList is a working buffer ... but it feeds the RTB which is
its own buffer too. This double buffering is inefficient of resources.
It works, it's relatively fast, but it also reflects my sloppy design.
Additionally, I Clear() the RTB each time I append or insert data into
the ArrayList buffer and then reload the RTB text.

I never learned MFC nor windows programming until now. Although I have
done a ton of numerical analysis type work. I do recall from Petzold's
Programming Windows 95 text that he moved a screen up a line and then
painted the new line when scrolling. For me to now Clear() the RTB and
rebuild it each time makes me feel like I am sloppy! I'd like to work
directly with the RTB buffer and eliminate the ArrayList if possible.
If I could insert and append into the RTB buffer beyond the viewing
area ... my thoughts are that I'd be taking advantage of what I
perceive to be very efficient RTB scrolling control.

Thanks for you input. It is always valuable!! I had not used the Lines
property as you illustrated. It's in my crosshairs now and I will
learn as I experiment with it. :)

-- Tom
 
P

Peter Duniho

[...]
The ArrayList is a working buffer ... but it feeds the RTB which is
its own buffer too. This double buffering is inefficient of resources.
It works, it's relatively fast, but it also reflects my sloppy design.
Additionally, I Clear() the RTB each time I append or insert data into
the ArrayList buffer and then reload the RTB text.

It's only "inefficient" in a relative sense. Maintaining two copies of
some very small subset of some large set of data is still more efficient
than maintaining two copies of that large set of data.

Could it be _more_ efficient? Sure. But assuming this mechanism is
working for you and the performance is adequate for your needs, it may in
fact be a fine solution. Simple, correct code that works is always better
than complicated, incorrect code that doesn't. Even if it's slower or
uses more resources (like memory). :)

That said, using a text box (rich or otherwise) there will be no way
around this problem. The text box maintains its buffer internally and you
don't have access to it. You can modify portions of it by creating a
selection and replacing that selection, using the SelectedText property.
And of course you can replace the entire text wholesale as illustrated in
this thread. But you can't fiddle with the text box buffers directly.

If you want a more efficient mechanism, you might be better off
implementing your own control, one that provides you direct access to
whatever data it's supposed to be displaying.

Pete
 
T

Tom

Hey all -- Here's an update on my progress. Again thanks for the
assistance to all. This update is perhaps of benefit to other newbs
who are working with the RichTextBox for the first time.

The key for gaining control of that RTB buffer is positioning the
caret, specifying the selection length, and using the SelectText
method. To insert without replacing any existing text ... simply set
the SelectonLength = 0. Simple, eh? But I did not realize this
amazingly simplistic technique and based on a review of other's
questions ... I'm not alone. Another simple technique is to set a
range of text equal to >> "". (Just a pair of double quotes with no
space.) The simplest null literal there is!! This is great for
deleting rows.

For example >>

textBox1.SelectionStart = textBox1.SelectionLength = 0;
textBox1.SelectedText = "This line is inserted at the start.\n";

Once I gained this simple understanding ... I was able to eliminate a
layer of buffering on my little project. Now I use the RTB's buffer as
the storage buffer. Scrolling up >> delete the bottom rows and insert
at the top. Scrolling down >> delete the top rows and append at the
bottom. Seems to be working very nicely. :) Now I have to implement a
ton of controls to make it dance the jig with some pizzazz.

Some helpful links I found along the journey include >>

http://www.personalmicrocosms.com/Pages/dotnettips.aspx?c=4&t=6#tip

http://msdn2.microsoft.com/en-us/library/aa140302(office.10).aspx

http://geekswithblogs.net/pvidler/archive/2003/10/15/182.aspx

http://www.syncfusion.com/FAQ/WindowsForms/FAQ_c89c.aspx

Just the RTF specification is over 250 pages! This topic can become as
in depth as you care to explore it. I just wanted the most basic of
skills and seemed to have difficulty getting my feet on the ground. If
you are in the same boat ... the above info might save you hours of
frustration.

Happy holidays everyone.

-- Tom
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top