|
An ordinary VB developer shares his own successes and failures |
|
||||||||||
| Home News Articles Resources Tips Downloads About me | ||||||||||||
RichTextLabel WinForms ControlEmbedding and displaying RTF resources to tweak the UI of an application easily and efficiently.A couple of weeks ago, I've had a busy weekend working on a soon-to-be-released .NET component. The feature I was working on was a nag dialog that the evaluation version of the component should display occasionally. Obviously, I wanted the dialog to show up quickly and also to look attractively. I also wanted to be able to display an active hyperlink that would take the user to the product's site when clicked. Let's go back to my nag dialog. As I said, I wanted to use formatted text and graphics to make it look nice and "cool". I've considered the following possible implementation options:1. Several differently formatted Label and LinkLabel controls.
I've abandoned this option quickly, because the formatted text should appear as "flowing" and I wasn't able to layout the differently formatted labels correctly. 2. Third-party HTML rendering controls. I've found a couple of ActiveX controls, but I didn't want to introduce any additional dependencies (and the interop overhead), so I didn't research the controls further. 3. Hosting the WebBrowser control.
This is an ActiveX control, so it suffers from the same drawbacks as the previous approach. It's also too slow for the purposes of my nag dialog. 4. The RichTextBox control.
The control supports text formatting and embedded graphics. It has also the DetectUrls property meaning it can underline properly formatted URLs, display
the 'hand' cursor when an user hovers the mouse over the link and it can also
raise the LinkClicked event when the link is clicked. The event can be handled
with a small amount of code to show the URL in the user's browser.
In addition, by setting a couple of the control's appearance properties, it could be made to look and act like a non-editable, formatted label. And the control's display performance is really good. For me, RichTextBox was a clear winner.
After deciding to use the RichTextBox, I've created an RTF file with the text
for my nag dialog (I've used the good ol' WordPad to do this). I've added the
RTF file to the component's project and marked it as an embedded resource:
I've added code to load the RTF text into the RichTextBox.Rtf property from
inside the nag dialog Load event handler, which was rather easy:
' Get a reference to this type's assembly.
Dim Assm As [Assembly] = Me.GetType().Assembly
' Open the required resource and load the RTF text from it.
Dim RtfStream As System.IO.Stream = Assm.GetManifestResourceStream("NagDialog.NagDialogText.rtf")
Me.RichTextBox1.LoadFile(RtfStream, RichTextBoxStreamType.RichText)
RtfStream.Close()
The stream returned from the Assembly.GetManifestResourceStream is simply passed
to the RichTextBox.LoadFile method.
The Assembly.GetManifestResourceStream method requires a resource name in the
form <Namespace>.<FileName>, where <Namespace> is the project's root namespace
and <FileName> is the actual file name (as it appears in the Solution Explorer).
Please bear in mind that the resource name is case sensitive.
I wanted the nag dialog to display the same product information that was already embedded into the assembly's manifest as attributes (i.e. AssemblyProductAttribute, AssemblyCompanyAttribute, etc.). In order to do that,
I've used substitution strings inside the RTF text. After loading the text, I've
replaced the substitution strings with the actual attribute values, for example:
Dim Attrs() As Object = Assm.GetCustomAttributes(GetType(AssemblyTitleAttribute), False)
If (Not Attrs Is Nothing) AndAlso (Attrs.Length > 0) Then
Me.RichTextBox1.Rtf = Me.RichTextBox1.Rtf.Replace("[0]", DirectCast(Attrs(0), AssemblyTitleAttribute).Title)
End If
My first attempt was to use substitution strings with curly braces (e.g. "{0}"),
suitable for passing to the String.Format method. However, I've quickly realized
that this approach won't work with RTF-formatted text, because curly braces have
special meaning in RTF (they're are used to enclose RTF groups). The only other
"forbidden" character is the backslash "\" character, so anything else can be
used.
The other thing to watch out when using string substitution in RTF is to make sure that the whole substitution string doesn't contain different formatting. Otherwise the string will get escaped in the RTF text and you won't be able to replace it. For example, if you enter "(0)" as a substitution string with the closing brace formatted as bold, you'll get "(0\b )" as a result. Let's recap quickly what you have to do in order to use RTF in a Form using the
described technique:
1. Write the RTF text in your RTF editor of choice (WordPad works quite well; Word adds too much overhead). Don't forget to add substitution strings for the product information that will be loaded from the assembly. 2. Add the RTF file to your project and mark it as embedded resource (set the Build Action property of the file to 'Embedded Resource'). 3. Place a RichTextBox control on your dialog and set its properties that will
make it look like a label (colors, TabStop, etc.).
4. Write code to load the RTF into the RichTextBox control and to do the
substitutions along the way.
It's quite boring, error prone work, so I've encapsulated the technique into an easy-to-use control - the RichTextLabel control:
The control is intended for reuse in source form. The accompanying solution (131 KB) contains both, the VB.NET version as well as the C# version of the control. The RichTextLabel control exposes just one, all important RtfResourceName
property. You'll need to set the property to the name of the RTF text resource
you wish to display in the control. Everything else is done automatically.
In order to use the RichTextLabel control within your project, you'll have to
follow these steps:
1. Add the RichTextLabel.vb or RichTextLabel.cs source file to you project and
recompile. The RichTextLabel control is derived from UserControl, so it will be added to the
Visual Studio .NET toolbox automatically.
2. Add an RTF file to your project and set its build action to 'Embedded Resource'. You can have the following substitution strings in the file:
3. Place the RichTextLabel control onto a Form and set its RtfResourceName
property to the name of the RTF file you've added in step 2.
In order to make things easier for you, the RtfResourceName property has an
associated type editor (RtfResourceNameEditor), which displays a popup list of
all the RTF resource files available in the current assembly:
In order to keep the RichTextLabel control as small as possible, I've put the
type editor in a separate LaMarvin.Windows.Forms.RichTextLabel.Design.dll
assembly that needn't be directly referenced by the project containing the
RichTextLabel control. If you want to take advantage of the richer design-time
support, just copy the LaMarvin.Windows.Forms.RichTextLabel.Design.dll assembly
to your project's output directory.
If you'd like to edit the RTF files added to your project comfortably from within the Visual Studio .NET IDE, you might want to associate the .RTF file extension with WordPad. Right-click on any RTF file in the Solution Explorer and select the "Open With..." command. In the Open With dialog box, add WordPad.exe to the list of available programs and set it as the default editor for .RTF files. After that, double-clicking an RTF file in the Solution Explorer will open the file in WordPad automatically. ©Palo Mraz, Saturday, March 20, 2004 |
||||||||||||
|
|
||||||||||||
| ©2003-2007 Palo Mraz. All Rights Reserved. See my 'new browser window' policy | ||||||||||||