
Taking a step back for a moment, I wanted to see whether using a RichTextBox control would improve our app. As you may recall, I started out with a RichTextBox but quickly switched to a TextBox control, which only works with plain text. But this may have been a mistake because the RichTextBox control provides additional functionality that we need.
Case in point: The position of the text caret, which is needed for that “Ln 1, Col 1” display in the Notepad status bar. The RichTextBox control provides properties related to the caret position, while TextBox does not.
To test whether obtaining and displaying this information was relatively easy, I did what I often do: I created a new Windows Forms app in Visual Studio and blocked it out with a basic menu, a basic status bar, and, in this case, a RichTextBox. And then I did a bit of Googling to figure out whether I could use the RichTextBox’s unique properties to display the row (line) and column position of the text cursor (caret).
This required a bit of work. The RichTextBox’s SelectionStart property, for example, can be used to get the cursor position relative to its starting position (0) in the RichTextBox. But it has no sense of row (line); instead, it just returns how many characters it is away from the starting position, regardless of the line.
But that was a good starting point. And RichTextBox provides other properties, like GetLineFromCharIndex and GetFirstCharIndexFromLine, which can be used together to calculate both the row (line) and column of the text cursor. So I eventually came up with the following code in the RichTextBox’s SelectionChanged event handler:
ToolStripStatusLabel1.Text = "Ln " + (RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart) + 1).ToString() + ", Col " + (RichTextBox1.SelectionStart - RichTextBox1.GetFirstCharIndexFromLine(RichTextBox1.GetLineFromCharIndex(RichTextBox1.SelectionStart)) + 1).ToString()
Calculating the row (line) is easy: The GetLineFromCharIndex property returns this value.
Getting the column looks more complicated, but it’s just a lot of code: Basically, the column is the number of characters that appear before the caret on the current line.
The “+1”s you see in there are due to Visual Basic using a zero-based positioning scheme, whereas Notepad starts at 1. The starting cursor position, from Visual Basic’s perspective, is 0, 0 (or “Ln 0, Col 0”). But Notepad displays that as “Ln 1, Col 1”. So I set that as the default value of RichTextBox1’s Text property. And then changed its value whenever the selection changed.
That seems to work properly when you just reposition the cursor. It doesn’t work like Notepad does when you select a block of text (by holding down the SHIFT key and using an arrow key to move the text cursor), however. That is probably solvable, but not a big deal in my opinion.
So that’s interesting. But the big issue with the RichTextBox in our Notepad clone is that it supports rich text formatting—bold, italic, and so on, plus things like hyperlinks—and even images. So the user can arbitrarily change the formatting of any text it contains. And they can paste rich text and/or image data into it and that information will appear correctly. That’s not how Notepad works: It works with plain text only.
It would be nice if the RichTextBox control simply had a Boolean property called PlainText (or similar) that would do the work for us. But it doesn’t. So we need to get a bit creative.
As it turns out, solving the pasting bit is easy enough: I created an Edit > Paste menu item and assigned it the CTRL + V keyboard shortcut, which ensures that we will intercept any paste attempts. Then, I used the following code in the PasteToolStripMenuItem_Click event handler to check whether the Clipboard contains text. If it does, it only pastes in the text, with no formatting (and no images).
If Clipboard.ContainsText Then RichTextBox1.SelectedText = Clipboard.GetText End If
That, too, seems to work just fine. Only plain text can be pasted into the RichTextBox.
But what about keyboard shortcuts? For example, the user might select a word or phrase and type CTRL + B to change it told bolded text. We don’t want to allow that. And I was thinking that we may have to figure out a way to intercept those shortcuts. But we don’t: Standard keyboard shortcuts like CTRL + B, CTRL + K, and CTRL + U don’t do anything by default. So that problem kind of solved itself.
(Kind of. CTRL + I actually deletes the selected text for some reason, so we’ll want to figure that one out.)
For the most part, it appears that replacing the TextBox we’re currently using with a RichTextBox might be a good choice. Of course, doing so this late in the project could be painful, too. And there are some bits, like my custom Zoom In, Zoom Out, and Restore Default Zoom code, that will need to be replaced. (The RichTextBox control supports zoom natively, unlike the TextBox.)
The question, of course, is whether it’s worth doing. I will experiment with that next, but for now, I just wanted to highlight some of the experimentation I do. The goal here, as always, is to make our Notepad clone as close as possible to the real thing. And making this switch might make that goal more attainable.
With technology shaping our everyday lives, how could we not dig deeper?
Thurrott Premium delivers an honest and thorough perspective about the technologies we use and rely on everyday. Discover deeper content as a Premium member.