Helpfile (*.chm) file not opening within embarcadero application

956 Views Asked by At

Problem

I am using Embarcadero C++ Builder XE. I am trying to trigger the opening of a help file (*.chm), when the user presses the F1 button on their keyboard. I thought I had done everything correctly, but I get no response/action when F1 is pressed.

What I did:

I have created a .chm help file (using Microsoft HTML Help Workshop). I have copied the compiled .chm file to the application directory. I have set:

Application->HelpFile = "My_Help.chm";

In the main form, I have set the HelpFile property to the same .chm file.

In the main form I have included the following two lines of code:

#include "HtmlHelpViewer.hpp"
#pragma link "HTMLHelpViewer"

The confusing thing is: I had this working a few weeks ago, and subsequently 'lost' the code :(

And since then, when I went to recreate the solution, I have had no success.

Also

If I define a help button, as detailed here ( embarcadero ), still nothing happens.

However, if I attach the following code to a button, the help file DOES open:

Application->HelpContext(0);

Question

Has anybody any idea why this would have worked before, but now it doesn't? Perhaps there is a simple step I did in the past and have forgotten, but I have searched all the help on this that I can find (including here at helpscribble), and covered all the steps as I see it. Any help would be much appreciated.

(I tried posting on the Embarcadero forums but that is a complete waste of time at the moment)

2

There are 2 best solutions below

3
On

I have experience in help authoring but I'm not a C++ programmer. Nevertheless, the C++ Builder Community Edition is installed on my Windows10 PC.

My SDIForm has following code snippet:

#include "Vcl.HTMLHelpViewer.hpp"
#pragma package(smart_init)
#pragma link "Vcl.HTMLHelpViewer"

I copied the CHM file (CHM-example.chm) into the build directories for simplification (Base, Debug and Release). It is working for me.

My resulting HTMLHelp Viewer window:

enter image description here

void __fastcall TSDIAppForm::Button1Click(TObject *Sender)
{
  Application->HelpContext(10000);
}
//---------------------------------------------------------------------------

void __fastcall TSDIAppForm::FormCreate(TObject *Sender)
{
  ShowMessage("The form has been created");
  Application->HelpFile = "CHM-example.chm";
}

After deleting the CHM file (CHM-example.chm) in the three directories mentioned above I tried following steps from the docs - this is working too. But please note I had to delete following code (see screenshot):

Application->HelpFile = "CHM-example.chm";

The usual way to designate the main help file for an application is using the HelpFile property of the global Application object.

Open the Project Options dialog box (Project > Options) and select the Appearance page (under Application). In the Help file option, specify the help file. Click Browse. By default, the Application Help File dialog box shows only files with the .hlp extension. To specify other types of help files, select the Any file (.) type in the Files of type control. Then you will be able to select help files of types such as .CHM, .HTML, and others.

This option sets the Application.HelpFile property. This property defines the main help file to the application. When the application receives any help-handling command, it, by default, uses this help file to execute the help command.

To specify an individual help file for a particular form, you can use the HelpFile property of this form.

0
On

Discoveries and a Workaround

I have made a few discoveries, and have come up with a work-around for now, until I learn more about this subject

DISCOVERY ONE

The HelpContext value seems to work if it is non-zero and valid (i.e. the ID is defined in the CHM file).

  • If I enter a non-zero and valid value, then the help file will open up (on the correct page) when I press F1 I am (almost) sure that a zero value used to work before - it would open the help file on the first / default page

DISCOVERY TWO

My main application (and I should have thought about this AND mentioned it before), consists of one form which contains a large number of frames. The main form holds a navigation menu and a frame holder space, and the frames are like 'pages' that the user can navigates to.

So, once I got to Discovery one (non-zero ContextHelp value), I noticed that the help file opened up on the same page, regardless of which frame was being displayed - even though I defined different HelpContext values for each frame.

So the HelpContext value of each frame does not seem to make a difference. I wonder if this is due to the fact that there are several frames overlayed at the same position, and the user navigation effectively involves making one frame visible and the previous frame invisible. However, Discovery Three makes me think otherwise.

DISCOVERY THREE

On one of the frames (‘pages’), I defined the following components: TGroupBox, TPanel, TStaticText, TCheckbox, TMemo and TButton

  • The ContextHelp values for the TGroupBox, TPanel and TStaticText components have no effect.
  • The ContextHelp values for the TCheckbox, TMemo and TButton components DO work

So it looks like the ContextHelp only works for interactive components – components that respond visibly to a click

Which is why I think ContextHelp values would never work for TFrame components.

DISCOVERY FOUR

I have a number of popup forms that are created and deleted on the fly throughout the use of the application. The ContextHelp values defined for these forms DO work.

WORK AROUND

I defined only non-zero and valid ContextHelp values for each form, including the main form

I defined a toolbar menu item (which I made invisible), and assigned the F1 shortcut to it. Now, when F1 is pressed, this menu’s OnClick event is run first, and then the regular OnHelp handling is called.

In the menu’s OnClick event, I determine which frame is currently ‘active’ (visible), and assign the desired ContextHelp value to the main form. Then the regular OnHelp handling is called, and uses this freshly assigned ContextHelp value to open the help file on the desired page.

FINALLY

I am reasonably happy with the workaround, as it requires me to list all the ContextHelp values in one function – which I was going to do for the frames anyway – for clarity and ease of maintenance.