Most folks who use computers a lot are aware of the difference between word processors and text editors. Text editors represent the data as pure characters — no formatting, no margins, no bold or italic.  The better text editors (Notepad++ is my current favorite) have lots of useful features, and typically can handle Unicode and Asian fonts, but when you save a document, what you’re really saving is a long list of binary numbers, each representing one character, and that’s all.  Word processors are different: in addition to the encoded characters, there are codes to indicate formatting, rendering of non-text elements like images or equations, and lots of other things that you usually can’t decipher because saved documents are compressed using proprietary algorithms. Open a MS Word doc as text, you get gibberish.

It’s often useful to be able to write programs that manipulate text. Python is ideal for applications that only need to read a text file, process it, and write it back out. But if the user needs to be able to interact with the program, it’s usually desirable to have a graphical interface, so Visual Basic.NET is the environment of choice. Among the available GUI controls, VB.NET does provide text boxes, which are adequate for displaying and editing pure text, but what if you need to be able to display more than just plain text? For example, what if you want to be able to highlight words found in a search? There is a solution: VB.NET also provides  a RichTextBox control that displays rtf format, which supports most common formatting and allows images. The downside: the RichTextBox control is  very finicky and hard to use. So I finally wrote a kind of wrapper for it which implements a lot of the functionality that you would think they would have built into RichTextBox but didn’t. I have posted the code on github here, together with a Windows installer for a simple word processing app based on it. In a future post I will describe a useful note-taking app that I built on top of it.

The standard RichTextBox control is fairly tricky to implement if you need it to do more than simple text editing (it’s very easy  to use for that). One of the main reasons is that it’s quite schizophrenic about keeping track of positions. Like any other word processing document, rtf uses codes to specify formatting. They aren’t visible in the display but they take up space in the encoded text. So the position of a word (say) in the document as it appears on the screen is not the same as the position of the same word in the underlying text. In a program, it’s often necessary to be able to convert between the two — some of the methods provided with the RichTextBox control work with one way of specifying position, some with the other, and getting the conversion between the two right takes quite a bit of experimenting. For example, if the program needs to be able to figure out the character position of the word at the beginning of the line that the user just clicked on, the code to do that isn’t necessarily simple, keeping in mind that GUI’s can be resized, moved, scrolled, etc. by the user.

In the RichTextBoxX wrapper that I have posted, I’ve more or less bludgeoned RichTextBox (via 630 lines of tedious code) into doing most of the things that one needs in a reasonable lightweight word processor — regex search, search and replace, block indentation, proportional or monospace font, highlighting, zoom, font sizes, etc. The showHelp method indicates the provided functionality. I don’t recommend this as a word processor — certainly there are better ones available — what it is intended for is a kind of turnkey control for use in VB applications that need more word processing functionality than the bare RichTextBox provides (it also may be useful as example code for someone trying to figure out how to get some of the more obscure RichTextBox functionality to work in a predictable way). Included with it is a very simple GUI form illustrating how to incorporate the RichTextBoxX and use it.

Leave a Reply

Your email address will not be published. Required fields are marked *