HelpProvider ignores form's HelpTopic on some controls

504 Views Asked by At

I've hit a frustrating issue with a software project I'm working on. I've got help set up on various forms such that if I press F1, the application's CHM file is opened.

I want it to always open to the topic related to the current form, however it currently opens to a different location depending on what part of the form is in focus. If some fields are in focus, it opens to the top of the first page of the help document; and if other fields are in focus it will open, correctly, to the page and heading related to the current form.

I have the following designer code for the various forms, and I'm only setting HelpKeyword on the form itself, not any of the form's controls.

this.helpProvider.HelpNamespace = @"Path\To\ChmFile.chm";
this.helpProvider.SetHelpKeyword(this, "TopicName.htm#heading_name");
this.helpProvider.SetHelpNavigator(this, System.Windows.Forms.HelpNavigator.Topic);

From experimentation, I've determined that items with either SetShowHelp(false) or Enabled = false are the only ones that show the correct chm help location. This applies when pressing F1 with them in focus (if they can hold focus), or pressing on them with the "what's this" help cursor.

As an example:

  • If focus is on the main dialog's first control (a TextBox which has a HelpString, which implicitly sets ShowHelp) and I press F1, I'll get sent to the overall application help page (undesired behaviour).
  • If focus is on a main dialog TextBox which does not have an associated help string, and I press F1, I'm shown the Dialogs help page, at the heading for the main dialog (desired behaviour).

The only workaround I've found for this so far is to set both HelpTopic and HelpNavigator on every control with a HelpString, but this is very heavy-handed and difficult to maintain.

Clarification

I am intentionally using both the "What's this?" help and the F1 help on the same forms. I will not accept a solution that says to disable "what's this" help for all controls on my form in order to allow the F1 help to work. It is a requirement for this application that interactive controls have a help tooltip, and that each dialog has a help section in the help document.

If there is no way to get these two help features to work together nicely, I will accept an effective workaround that does not sacrifice maintainability as my above workaround does.

1

There are 1 best solutions below

1
On

It was only after your clarification that I was able to fully understand your question and reproduce the problem. This behavior was not known to me before. Same undesired behaviour using Visual Studio 2019 on Windows 10 PC - it does not matter if it is coded in the Form_Load event or with the help of the IDE (Integrated Development Environment) in the designer code.

After some hours of experimenting (with the reproduced problem) I hopefully narrowed it down without fully knowing the real reason.

I have done the following steps and thoughts - FYI - experimentally (see special notes in the list below):

  • The default value of the HelpNavigator enumeration is AssociateIndex. If you accidentally set SetShowHelp = True and a required property is missing, the call to the Index tab may fail, corrupt something and goes to the CHM's home page topic. If you don't have an index tab in your CHM, another problem arises.
  • I deleted or renamed the file hh.dat several tines to reset all (!) CHM windows on my system to their default settings. Windows will create a new version of hh.dat when you next open any .chm file. You'd find hh.dat at C:\Users\%username%\AppData\Roaming\Microsoft\HTML Help. BUT - - no success with the existing problem in the first test phase.
  • For some more test only (code is not required later) I have tried if the Form3_HelpRequested is triggered. BUT - that did not work in the first test phase.
    private void Form1_HelpRequested(object sender, HelpEventArgs hlpevent)
    {
      // do whatever you're gonna do here
      DialogResult dr = MessageBox.Show("HelpRequested on Form1 was fired!\n\nOpen CHM help?","Test case", MessageBoxButtons.YesNo);
      switch (dr)
      {
        case DialogResult.Yes:
          // FALSE will also open any associated help file 
          hlpevent.Handled = false;
          break;
        case DialogResult.No:
          // TRUE will prevent windows from also opening any associated help file
          hlpevent.Handled = true;
          break;
      }
  • Last as a hard step I deleted the HelpProvider component, have inserted this again and set all properties correctly a second time. NOW - it is working for me. Controls with the property ShowHelp=True now show the assigned topic and controls with the property ShowHelp=False now show the help topic of the form as expected.

You know - this can be a complex step and should be done in a test environment first. Make sure that all properties are set correctly and that the topic is accessible in the CHM via HelpKeyword.

// Tell the HelpProvider what controls to provide help for, and what the help string is.

this.helpProvider1.SetShowHelp(this.cityTextBox, true);
this.helpProvider1.SetHelpNavigator(this.cityTextBox, HelpNavigator.Topic); // make sure to set "Topic"
this.helpProvider1.SetHelpKeyword(this.cityTextBox, @"/Garden/flowers.htm");
this.helpProvider1.SetHelpString(this.cityTextBox, "Enter the city here.");

After giving the city textbox focus and F1 the help viewer window is shown. Using the "What's this" ? button in a second step is resulting in:

enter image description here


tl;dr

The definition of the properties via designer code or program code is more a decision based on personal preferences. I myself prefer to set values in the program code rather than via the controls properties window of Visual Studio.

If you add here all the properties of the controls for the help functionality as code, you can easily comment out for fixing problems. In a form with many controls, it is easier to save parts of the code externally and insert them again later. But as I said - everybody likes it different.

// set F1 help topic for first form
private void Form1_Load(object sender, EventArgs e)
{
  helpProvider1.SetHelpNavigator(this, HelpNavigator.Topic);
  helpProvider1.SetHelpKeyword(this, @"/HTMLHelp_Examples/Jump_to_anchor.htm#SecondAnchor");
}

BTW - the "What's this?" help for large programs means a high effort and in my experience it is used less and less in help authoring (CHM's). This kind of help has a long history from the times of Visual Basic 6, for example. Today you often find only one help topic for a form or a dialog in which the single controls are explained. The problem you describe then does not appear at all.

FYI - in earlier days a ALIAS and MAP files was required and maybe used today by TopicId. The purpose of the two files is to ease the coordination between developer and help author. The mapping file links an ID to the map number - typically this can be easily created by the developer and passed to the help author. Then the help author creates an alias file linking the IDs to the topic names.