This is a serious design flaw in HtmlHelpViewer
. And it's easy to reproduce the behaviour you describe. Well done for specifying the problem so clearly. The issue afflicts both 32 and 64 bit programs equally.
Personally I don't use HtmlHelpViewer
because it just doesn't work. I implement a handler for TApplication.OnHelp
. It looks like this:
class function THelpWindowManager.ApplicationHelp(Command: Word;
Data: THelpEventData; var CallHelp: Boolean): Boolean;
begin
CallHelp := False;
Result := True;
//argh, WinHelp commands
case Command of
HELP_CONTEXT,HELP_CONTEXTPOPUP:
HtmlHelp(GetDesktopWindow, Application.HelpFile, HH_HELP_CONTEXT, Data);
end;
end;
Put that in in a class and assign it to Application.OnHelp
on startup:
Application.OnHelp := THelpWindowManager.ApplicationHelp;
I've just tested that out on the trivial two form application and it works well. In real code you may wish to embellish this. For example, my actual code is more complex. It stores in user settings the position and window state of the help window when it is closed. And then when shown again, that position and window state are restored. So that the help window appears to remember where it last was on the screen.
Thanks to @Sertac for dredging out the details in the comments below. In summary here's where the HtmlHelpViewer
code goes wrong:
- It makes sends the
HH_INITIALIZE
command at help system startup. - As described in the documentation this configures HTML Help to run on the same thread as the calling application instead of a secondary thread.
- When you call
ShowModal
that callsDisableTaskWindows
which disables windows in the calling thread. - Because the help viewer window was created by your app's main thread (because of the
HH_INITIALIZE
command), it gets disabled.
And that's why you cannot interact with the a pre-existing help window whilst a Delphi modal form is active.