What do you hate the most? Well your answer may vary but for most of you it would likely be something around the documentation! Am I right?
A long time ago (back in December 2004), I showed you how to build a real help system based on help files that you have to build yourself and link your application to (see Creating help files and linking them to a VB application). Have you built many since that time even if you know how to do it now?
If your users are like mine, they always find that the help files, if you decide to build any, are never complete or up-to-date. This is often because documentation and/or help files are the last thing done in a project and very often you don’t do it because you have to jump on something else.
This month, my column will show you how to save time on the creating help files and ensure that users cannot blame you if those files are not updated. Why not let the users create their own help system and maintain it? This is a very good idea that one of my friend (thanks Nicolas) told me lately. A kind of wiki but still sensitive to the form the users are on.
Because I am using the RichTextBox control, rich text formatting and images are natively supported. Users are also able to copy existing text from an application such as Microsoft Word directly to your RichTextBox control. I am sure they will like it.
I also want the help to be context-sensitive but I don’t want to go to deep. I only want to detect on which I am and display the help related to this form. I don’t want to have a big endless scrolling textbox that user will complain that it is too long.
The basic form
I will start by showing you the form that will be used by users to enter the text as shown in figure 1.
Figure 1: The help form
It is composed of only 3 controls: a ToolStrip, a RichTextBox control, and a checkbox.
The toolbar let the user do usual task such as clear the current text, save the text, cut, copy, paste, change the font of the selected text, and change the color of the selected text. When I have added the ToolStrip control to the form, I used the smart tag actions to insert standard items as a start point. I removed a couple of unwanted buttons (open, print, help) and added a few more (font and font color).
The second control on this form is the RichTextBox control which is the easiest way to let user have a real text editor that allows great features such as pasting content from Microsoft Word.
The last control is a CheckBox that will let the user to use the help form outside the MDIParent form. This is simply done by setting the MdiParent property of the form to Nothing. This is really simple but with more and more users having more than one screen attached to their PC, users start to ask to be able to detach some of the forms from the MDIParent container.
If you need details on how to work with the ToolStrip control, refer to an article I have written on that topic in May 2006 - The Strippers’ club. If you need details on the Font dialog and/or the Color dialog, refer to another article I have written in June 2003 - Common Dialogs.
Persisting data
For this demo, the data entered by user as the help text is persisted into a dataset which is saved as a XML file when the application is closing using the WriteXml method of the dataset object.
This is one thing you will surely want to improve in order to correctly support concurrent users.
I always prefer to save that kind of data into a real database but it would have been harder for you to quickly try this demo application.
When the fMDIParent form loads, the OpenHelpDataset method opens the XML file and loads it into a dataset object or creates a new dataset if the file does not exist:
Private Sub OpenHelpDataset() If Not IO.File.Exists("Help.xml") Then mHelpDataset = New DataSet Dim dt As New DataTable With dt .TableName = "HelpTable" With .Columns .Add("Code", GetType(String)) .Add("HelpText", GetType(String)) End With End With mHelpDataset.Tables.Add(dt) mHelpDataset.DataSetName = "HelpDataset" Else mHelpDataset = New DataSet mHelpDataset.ReadXml("Help.xml") End If End Sub
Private Sub SaveHelpDataset() mHelpDataset.WriteXml("Help.xml") End Sub
Integrating the help form into a MDI project
Now that we have our help form almost ready, it is time to integrate it into an application.
You could add a button on each form that creates a new instance of the help form but I will use another method. I will suppose that your application is a MDI application and that your main form has a toolbar and/or a menu (I don’t think that I am off the track here!). In my demo application, I have added a MDI parent which already comes with a menu and a toolbar that I have trimmed a bit.
When the help button or menu item is selected, you need to find which form is currently active in order to display the help that goes with this form. So detecting the active is the first task to do. So I try to find the ActiveMdiChild name, if it is not working, I try the ActiveForm (which would be a standalone form). If neither works, I suppose that no forms are currently opened and force the main help to appear. It is really important to catch exception here because nothing guarantees that a form exists:
Dim strCurrentForm As String = String.Empty Dim strFormTitle As String = String.Empty 'Try to find a child form Try strCurrentForm = ActiveMdiChild.Name strFormTitle = ActiveMdiChild.Text Catch ex As Exception strCurrentForm = String.Empty End Try 'Try with the active form If strCurrentForm.Length = 0 Then Try strCurrentForm = ActiveForm.Name strFormTitle = ActiveForm.Text Catch ex As Exception strCurrentForm = String.Empty End Try End If 'No forms - We are surely on the MDI parent If strCurrentForm.Length = 0 Then strCurrentForm = "Main" strFormTitle = "Main form" End If
Dim f As New fHelp f.MdiParent = Me f.LoadHelpForm(strCurrentForm, strFormTitle, mHelpDataset) f.Show()
Figure 2: The demo application in action
Extending this system
I am sure you will have many ideas to enhance this feature even more.
You could start by providing a richer ToolStrip control for editing. Before doing it all by yourself, have a look at what Richard Parsons has posted on the CodeProject web site. It is a wrapper component containing a Toolbar control and a RichTextBox control written in C# that you can plug into your application.
If you build a small table containing the hierarchy of your forms, you could easily show a treeview to let the user navigate between the different help pages.
It would also be nice to be able to print those topics. With the hierarchy of the previous idea, it could be possible to create a table of content and print it in a logical order. If you are interested to try something like this, have a look at Aspose.Words which is a commercial component (meaning not free) that could be very helpful if you want something which is more robust to use then Microsoft Word automation.
Conclusion
Now the pressure is on the users to keep the help system ... helpful and up-to-date. I am sure they will appreciate the fact that they can put their own wording into what THEY used. After all, the help is built for them, why not by them?
I hope you appreciated the topic and see you next month.