Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
Print
(untagged)

Integrate Help Into Your .NET Apps

0.00/5 (No votes)
11 Apr 2004 6  
An article on how to leverage .NET to integrate Help into your applications.

Introduction

The .NET framework offers us the Help class and the HelpProvider component to seamlessly integrate a Help system into our applications. Surprisingly, integrating the regular done-to-death Help techniques into your application with the use of the HelpProvider component in .NET is insufficiently illustrated in the VS.NET documentation. However, learning on your own, turns out to be anything but difficult.

"The Windows Forms HelpProvider component is used to associate an HTML Help 1.x Help file (either a .chm file, produced with the HTML Help Workshop, or a .htm file) with your Windows application. The HelpProvider component can be used to provide context-sensitive Help for controls on Windows Forms or specific controls. Additionally, the HelpProvider component can open a Help file to specific areas, such as the main page of a table of contents, an index, or a search function."-MSDN

With VB6, I should admit that Help was perhaps the last feature I was inclined to incorporate into an application. Even providing pop up context-sensitive help windows required garnering Win32 API support (getting enough info was tough by itself). With .NET, this tendency of mine (and that of anybody else who can be just as lazy) has begun to disappear. It is so easy to provide the pop-up window support now, that I use them right from the start of UI construction.

.NET immediately allows your help system to be based on a pop-up-window or/and online/offline HTML approach. The .CHM file approach is my favorite, simply for the Keyword Indexing feature, if not for anything else. Let's face it. No approach is without pitfalls. An online help would make maintainability sleek and accurate, but not many applications warrant the need for a user to connect to the Internet to get some assistance. This article will demonstrate how to include each approach using the leverage .NET offers. Note that the ToolTip and background information on how to create Help files using HTML Help Workshop will not be discussed.

Background

HelpProvider Class

"Provides pop-up or online Help for controls. ��Each instance of HelpProvider maintains a collection of references to controls associated with it."-MSDN

The HelpProvider component implements the very special IExtenderProvider interface, whereby it becomes capable of providing extra properties to other components. MSDN gives a decent description about the interface, so I suggest that the insatiable reader look it up.

The HelpProvider component can be dragged on to your Windows Form from the Toolbox. It will likely be automatically named HelpProvider1. I normally change it to something like hlpPrvMain or anything more appropriate and on the mark. The only really relevant property you need to set at design-time is the HelpNamespace property, which holds a string value representing the path to the HTMLl Help source file. The source file may be any .htm or .chm file. However, I later found that it could be used to point to even a .txt file or any file for that matter, only that it serves very little purpose. Alas!

Extender Properties

The HelpProvider component associates itself very neatly with your form and all the controls on it without ado. You can make sure of this fact by checking for HelpXXX properties that come out of nowhere for every control in the Properties window. I have read somewhere that the component maintains a separate hashtable for each property it provides to all external objects. The properties added include the following: -

  1. HelpButton

    This property takes a boolean value and determines whether the Help symbol (?) appears on your form in the control box. The button will however appear only if the MaximizeBox and MinimizeBox properties for the form are also set to false. Hence, the Help button is a feature normally seen only on Dialog forms.

  2. HelpNavigator

    Specifies a constant indicating which elements of the Help file to display. It can be any one of the values in the Enum HelpNavigator (as listed in MSDN): -

    TABLE 1.

    Member name Description
    AssociateIndex Specifies that the index for a specified topic is performed in the specified URL.
    Find Specifies that the search page of a specified URL is displayed.
    Index Specifies that the index of a specified URL is displayed.
    KeywordIndex Specifies a keyword to search for and the action to take in the specified URL.

    TableOfContents Specifies that the table of contents of the specified URL is displayed.
    Topic Specifies that the topic referenced by the specified URL is displayed.
  3. HelpKeyword

    The Help keyword provides the key information to retrieve the help associated with this control from the Help file specified by HelpNamespace. It takes a string value that means different things for different values of the HelpNavigator property. Refer to table 2 below.

    TABLE 2.

    HelpNavigator Value What the HelpKeyword value represents.
    AssociateIndex Applies exclusively to .chm files. The string value is treated as a match criterion to find the most minimal match in the Help Index that would be just enough to get a unique hit. But the topic is not displayed.
    Find Applies exclusively to .chm files. The string value is seemingly ignored resulting in the Find section of the Help file being displayed.
    Index Applies exclusively to .chm files. The string value is entered into the Index Find textbox, but the related topic is not displayed.
    KeywordIndex Applies exclusively to .chm files. The string value is not only entered into the Index Find textbox, but the related topic is displayed as well.
    TableOfContents Applies exclusively to .chm files. The string value is seemingly ignored resulting the Contents section of the Help file being displayed.
    Topic The string value is taken as the name of a file. The value can optionally include an anchor. E.g., �index.htm#top�.
  4. HelpString

    The HelpString value represents the help message of the pop-up help windows that appear when the user requests for Help using the Help button or by pressing F1.

Important Public Members

At design-time, you can associate an instance of HelpProvider with only one Help source. Your Help source can be set through the HelpNamespace property which accepts a string value representing the path to your .htm or .chm file. This property is the only useful property exposed in the component. It is used to contain the name of the help file, which may be an .htm or .chm file (there is nothing stopping you from providing a path to a text file or even a .exe file, but doing so is not really useful). Additionally, it exposes quite a few useful methods: -

  1. SetHelpKeyword

    Specifies the keyword used to retrieve Help when the user invokes Help for the specified control.

    VB.NET
    Overridable Public Sub SetHelpKeyword (ByVal ctl As Control, _
        ByVal keyword As String) 

    This string value is used to find the specific help section in the help file that pertains to the specified control.

  2. SetHelpNavigator

    Specifies the Help command to use when retrieving Help from the Help file for the specified control.

    VB.NET
    Overridable Public Sub SetHelpNavigator (ByVal ctl As Control, _
           ByVal navigator As HelpNavigator)

    This method determines which element of the Help File to Display.

  3. SetHelpString

    Specifies the Help string associated with the specified control.

    VB.NET
    Overridable Public Sub SetHelpString (ByVal ctl As Control, _
       ByVal helpString As String)

    This method sets the Help string, but does not display the pop-up message. The pop-up will appear the next time the user presses F1 on the control.

  4. SetShowHelp

    Specifies whether Help is displayed for the specified control.

    VB.NET
    Overridable Public Sub SetShowHelp (ByVal ctl As Control, _
           ByVal value As Boolean)

    This method is used to override the flag that determines whether the Help for a control will be displayed or not.

The above-mentioned SetXXX methods have related GetXXX methods as well, as listed below:-

  1. GetHelpKeyword
  2. GetHelpNavigator
  3. GetHelpString
  4. GetShowHelp

The HelpProvider also registers event handlers on each control's HelpRequested and QueryAccessibilityHelp events.

Help Class

"Encapsulates the HTML Help 1.0 engine. ��You can use the Help object to show compiled Help files (.chm) or HTML files in the HTML Help format. Compiled Help files provide table of contents, index, search, and keyword links in pages. Shortcuts work only in compiled Help files. You can generate HTML Help 1.x files with the HTML Help Workshop."-MSDN

This is another class that has very little documentation. Look it up on MSDN, here's what you will be told - "This member supports the .NET Framework infrastructure and is not intended to be used directly from your code". Regardless, note that it is found in the System.Windows.Forms namespace, and used to explicitly display Help files from your code. It exposes two useful shared/static methods for our consumption:-

  1. ShowHelp

    Displays the contents of a help file.

    To display the contents of the Help file at the specified URL:

    VB.NET
    Overloads Public Shared Sub ShowHelp(ByVal parent As Control, _
       ByVal url As String)

    To display the contents of the Help file found at the specified URL for a specific topic:

    VB.NET
    Overloads Public Shared Sub ShowHelp(ByVal parent As Control, _
      ByVal url As String, ByVal navigator As HelpNavigator)

    To display the contents of the Help file found at the specified URL for a specific keyword:

    VB.NET
    Overloads Public Shared Sub ShowHelp(ByVal parent As Control, _
       ByVal url As String,ByVal keyword As String)

    To display the contents of the Help file located at the URL supplied by the user:

    VB.NET
    Overloads Public Shared Sub ShowHelp(ByVal parent As Control, _
      ByVal url As String, ByVal navigator As HelpNavigator, _
      ByVal param As Object)

    I learnt a very interesting thing about this method. It will open just about any URL you provide to it. The URL can point to any local or remote resource. It was a pleasant surprise to know that it could even run an EXE file. Very interesting indeed! In overloaded versions that require extra parameters, pass in Nothing and you will infer that those parameter values are ignored, or at least they don't interfere with running the file.

  2. ShowHelpIndex

    Displays the index or search window of a help file.

    VB.NET
    Public Shared Sub ShowHelpIndex(ByVal parent As Control, _
        ByVal url As String)
  3. ShowPopUp

    Displays pop-up help at chosen location on screen.

    VB.NET
    Public Shared Sub ShowPopup( ByVal parent As Control, _
      ByVal caption As String, ByVal location As Point)

Using a HelpProvider object to add Pop-up Help

Pop-up help involves providing context-sensitive information for a control or a form. The help message or information is embedded in your code. The context-specific pop-up help message will be displayed when a user presses F1 on the control that has the focus.

Once the HelpProvider component has been added to the Form, we can set the HelpString for every control on the form we intend to provide Help. Depending upon the number of HelpProvider components you have made use of, you will find an equal number of HelpString properties for very control, pertaining to each HelpProvider instance. Set the value of the HelpString property (of the HelpProvider you want to use to provide pop-up help) to a useful message for each control. Make sure the ShowHelp property (pertaining to the same HelpProvider instance) is set to true for the concerned controls. It would be advisable to use a single HelpProvider to provide pop-up help on the same form just to make maintenance a lot easier. Once these two properties are set at design time, our work is done! None of the other newly available properties need to be configured.

The same design-time configuration can be done by code as well. However, the properties that we set at design-time for each control using the Properties window are not available at runtime. Instead, we make use of the SetHelpString method of the HelpProvider component, or the Shared Help.ShowPopUp method as illustrated below.

VB.NET
Help.ShowPopup(Me, _
  "Enter Phone number here. Valid input characters are 0-9,space,'-','(', and ')'", _
  Cursor.Position)

OR

VB.NET
'Setting the help string automatically enables 

'the pop-up display for the control.

hlpPopUp.SetHelpString(txtCity, _
  "You pressed F1 on the City field. How can I help you?")
'The following invocation is not necessary if you intend 

'to keep the pop-up enabled.

'However, the Pop-up display can be disabled for the control 

'if the second argument to this method takes a boolean False value. 

hlpPopUp.SetShowHelp(txtCity, True)

See the Pop-up Demo in the code that comes with this article.

Enabling The Help Button

The Help button (appears with '?' as its text.) occurs on the RHS of your title bar as shown in the picture below (the images come from some quick demo apps I put together for the article).

You can enable this button for your form by setting its boolean HelpButton property to True. The catch in using this button in your forms is that you have to do away with the Maximize and Minimize boxes in the title bar. So, go ahead and set the MaximizeBox and MinimizeBox properties to False.

Clicking the Help button at runtime will change your cursor to show "?". With the new cursor displayed, click on the field for which you may have set the HelpString property and the pop-up Help should now get displayed.

See the Pop-up Demo in the code that comes with this article.

HelpRequested Event

Every control, including the form, raises its own HelpRequested event in response to a user pressing the F1 button. We are rightly advised to do our Help invocation implementation here if we want to exercise greater control over the process.

Example:

VB.NET
Private Sub txtPhone_HelpRequested(ByVal sender As Object, _
ByVal hlpevent As System.Windows.Forms.HelpEventArgs) _
Handles txtPhone.HelpRequested
Help.ShowPopup(Me, _
"Enter Phone number here. Valid input characters are 0-9", _
hlpevent.MousePos)
End Sub

However, it is possible to respond to a user's help request from the KeyDown or one of the other key-related events as well, simply by screening for the KeyCode value and performing the necessary action if it evaluates to the F1 button. Note that the HelpRequested event will fire regardless after key-based events.

'E.g.,
Private Sub txtPhone_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) Handles txtPhone.KeyDown
If e.KeyCode = Keys.F1 Then
Help.ShowPopup(Me, _
"Enter Phone number here. Valid input characters are 0-9",Cursor.Position)
e.Handled = True
End If
End Sub

Adding Offline/Online .Htm Help

Using HelpProvider Class

The first step would be to set the HelpNamespace property to a valid URL. The URL will be a local path for an offline web page or a remote URL (e.g., "http://www.codeproject.com") for an online web page. At design-time, you can hard code the path to your help resource in the HelpNamespace property of the HelpProvider component.

This much will suffice to get the page to display in your default browser when the user presses F1. You don't really have to change any other properties.

To use the same HelpProvider component to display different web pages for different contexts, you have to programmatically change the HelpNamespace property value to the appropriate Help resource. You can do the change in the HelpRequested event.

VB.NET
'E.g.,

Private Sub lnkOpenHtmHelpIndex_HelpRequested(ByVal sender As Object, _
ByVal hlpevent As System.Windows.Forms.HelpEventArgs) _
Handles lnkOpenHtmHelpIndex.HelpRequested
    hlpPopUpAndHtm.HelpNamespace = IO.Path.GetDirectoryName(.HelpNamespace) & _
    "\help_on_city.htm"
End Sub

It is also easy to open your help web page in response to other user events, like say a click event. Take a look below:

VB.NET
'E.g.,

Private Sub lnkOpenHtmHelpIndex_LinkClicked(ByVal sender As System.Object, _
ByVal e As System.Windows.Forms.LinkLabelLinkClickedEventArgs) _
Handles lnkOpenHtmHelpIndex.LinkClicked
    hlpPopUpAndHtm.HelpNamespace = IO.Path.GetDirectoryName(.HelpNamespace) & _
    "\help_on_city.htm"
    'To send F1 keystroke to the active application and 

    'get the help file displayed.

    SendKeys.Send("{F1}")
End Sub

See the Help File Demo in the code that comes with this article.

Using Help Class

Just in case, you wish to use the System.Windows.Forms.Help class for the same, then we have to do something like this:-

E.g.,

VB.NET
Help.ShowHelp(Me, "http://www.codeproject.com")'A fab site

Or

VB.NET
Help.ShowHelp(Me, "\Help\index.htm") 'a path local to the client App.

See the Help File Demo in the code that comes with this article.

Adding Offline/Online .chm Help

Using HelpProvider Class

Associating the HelpProvider component with a .chm file is the most preferred way of going about designing and integrating a help system for a WinForms application from what I hear, and not without obvious reasons. Compiled help files provide table of contents, index, search, and keyword links in pages.

So first things first! Set the HelpNamespace property of the component to a valid URL that points to your .chm help file. The .chm file is normally located at an address local to the client, but there may be needs for the file to be located on a remote location on a LAN or the Internet. Regardless, the property value should pay heed to your need.

With that done, set the "ShowHelp On HelpProvider" for the control (for which you want to associate with the Help file's contents) to true. Choose an appropriate HelpNavigator Enum value so that the desired section of the help file will be opened and queried using your HelpKeyword value. The latter should hold a context-specific keyword that you had included in the Help file before compilation. It could be an index entry, a search value or the name of a file that is part of the compilation. In each case, the value of the HelpNavigator has to be set to specific values as explained in table 2 presented earlier in this article.

That's all there is to be done at design time.

If you want to change the HelpKeyword and/or the HelpNavigator properties of a control at runtime, use the SetHelpKeyword and/or the SetHelpNavigator methods of the HelpProvider component.

See the Help File Demo in the code that comes with this article.

Using Help Class

The Help class can be used during runtime to display the contents of your .chm file as well.

To show the table of contents, do something like this:

VB.NET
Help.ShowHelp(Me, "Help\VB.chm", HelpNavigator.TableOfContents)

Change the HelpNavigator Enum value to show other sections of the help file.

If you want to show the Index section, either one of the two statements should do the job:

VB.NET
Help.ShowHelpIndex(Me, "Help\VB.chm")

OR

VB.NET
Help.ShowHelp(Me, "Help\VB.chm", HelpNavigator.KeywordIndex)

To display a particular file in the compiled help source, try the following:

VB.NET
Help.ShowHelp(Me, "Help\VB.chm", "help_on_name.htm")

See the Help File Demo in the code that comes with this article.

Associating Alternate Keys To Invoke Help

It is not entirely necessary to associate Help with the F1 key alone. It's real easy to launch help using any other key or combination, but you have to provide code for that end.

E.g.,

VB.NET
Private Sub txtName_KeyDown(ByVal sender As Object, _
ByVal e As System.Windows.Forms.KeyEventArgs) _
Handles txtName.KeyDown
    If e.KeyCode = Keys.F1 And e.Alt Then
    Help.ShowPopup(txtName, "This is an alternative help message", _
    New Point(Me.Location.X + txtName.Location.X, _
    Me.Location.Y + txtName.Location.Y))
    End If
End Sub

Points of Interest

It would be interesting to know that when you invoke a web page (whether local or remote) using the Help.ShowHelp method, you are opening your browser window in an external process. This means that when your client application process dies, the browser process holds its ground unless you had earlier closed it yourself. It can be embarrassing if your Help file hangs around after the application that called it has shut down. However, it does not happen with .chm files that are opened with the HelpProvider component.

As a work around, I suppose we could use an instance of the Process class found in the System.Diagnostics namespace. Here's a quick snap class I devised solely for demonstrating my idea. It could and should rightly be bettered before it's actually used.

VB.NET
Namespace KingLeon
Public Class Help 
    Public Shared Function ShowHelp(ByVal url As String) _
    As System.Diagnostics.Process 
        Dim startInfo As New Diagnostics.ProcessStartInfo() 
        With startInfo 
        . FileName = url 
        .WindowStyle = ProcessWindowStyle.Normal 
        End With 
        Return System.Diagnostics.Process.Start(startInfo) 
    End Function 
    Public Shared Sub CloseHelp(ByVal proc As System.Diagnostics.Process) 
        If Not proc Is Nothing Then 
            If Not proc.HasExited Then proc.Kill()
        End If 
    End Sub 
End Class
End Namespace

The method KingLeon.Help.ShowHelp is a function that returns a Process object. This Process object can be stored in a collection in the calling application for later reference in case the application decides to shut down. In which case, we will have to iterate through each Process object in the collection and call the KingLeon.Help.CloseHelp method, which takes a Process object as a parameter. The collection I used was the ArrayList, which I simply rate as one of the best things .NET provides.

VB.NET
'E.g.,

'Declare the collection to hold the process objects 

Private procList As New ArrayList()
........
........
........
Private Sub mnuItmOnlineHelp_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles mnuItmOnlineHelp.Click
    procList.Add(KingLeon.Help.ShowHelp("http://www.codeproject.com"))
End Sub
........
........
........
Private Sub frmHelpFile_Closing(ByVal sender As Object, _
ByVal e As System.ComponentModel.CancelEventArgs) Handles MyBase.Closing
    If Not procList Is Nothing Then
        Dim i As Integer
        For i = 0 To procList.Count - 1
            KingLeon.Help.CloseHelp(CType(procList(i), Diagnostics.Process))
        Next
    End If
End Sub

See the Help File Demo in the code that comes with this article.

Using the code

The code with this article gives simple demonstrations on how what we have discussed in this article can possibly be used. The two main classes of interest are frmHelpFile.vb and frmPopUp.vb. The former illustrates how to interact with a file-based Help System, while the latter shows how pop-up based Help can prove useful. Fair enough?

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here