6

I'm working on getting the helpfile setup with our software. I have added HelpContext numbers for lots of specific forms/frame/controls and they all work fine. The problem is that the main form is not bringing up any help at all. For all of this I'm only using F1 to try to trigger the help.

I'm not at all an expert on Delphi or helpfiles, but I'll post what I've done and where I've looked.

Edit: Thanks to some help I now see the issue is due to the main form being a MDI parent. This still doesn't solve the problem.. it almost seems like a bug to me but I suppose it could be intentional for some reason. EndEdit

I'm including this unit: HtmlHelpViewer for the viewer. In the main forms Create constructor I've added the Application.Helpfile := 'asdf.chm'. For all the other forms I have just added context numbers and it's worked right away. I tried that on the main form and nothing happens. So I tried adding an Application.OnHelp event but this doesn't get called on the main form (and it does for all the other forms where help is working).

Last resort that I could think of was to trace deep down into the code and see what was happening. I got to TCustomForm.WMHelp in Vcl.Forms as the place where the split was happening. Said function has this loop:

if iContextType = HELPINFO_WINDOW then
begin
  Control := FindControl(hItemHandle);
  while (Control <> nil) and ( not ControlHasHelp(Control)) do
    Control := Control.Parent;
  if Control = nil then Exit;
  GetHelpInfo(Control, HType, ContextID, Keyword);
  Pt := Control.ClientToScreen(Point(0, 0));
end

When the main form was calling the Help Control would be nil and then it would exit. Anything else would go on fine.

I obviously don't know why this is happening. The answer could be something very basic. Any ideas would be appreciated!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
Sentient
  • 1,102
  • 12
  • 29
  • Did you set `HelpContext` for the main form itself? – David Heffernan Apr 02 '12 at 23:03
  • @DavidHeffernan: Yes I did. I should have mentioned this, but it's just the main form, not its children. I put a button on the form (with no context help) and when it has focus and I push F1 the helpcontext for the main form loads. If there's no visible focus then no help loads. – Sentient Apr 03 '12 at 15:23
  • I'd have a look at the WMHelp handler under the debugger and see what is returned from FindControl. – David Heffernan Apr 03 '12 at 15:24
  • @DavidHeffernan I looked down through that but it doesn't seem very helpful. FindControl is returning nil for the form and a result for controls that work, but when I go to see why I get to this line 'Result := Pointer(GetProp(Handle, MakeIntAtom(ControlAtom)))' (in Vcl.Controls, FindControl) And for a control that links, that returns something. But when for the main form it return nil. I can't debug any deeper because it just goes to a property (or something that kind of looks like one). – Sentient Apr 03 '12 at 15:47
  • 1
    Well, this is getting to the nub of the problem. FindControl returning `nil` is why no help appears. The question is why that is so. Next step is to look at what `hItemHandle` is and try to identify it. I'd be using Spy++ to debug that part of it. – David Heffernan Apr 03 '12 at 16:03
  • @DavidHeffernan That did get me somewhere.. I think. I found the tool (don't have Visual Studio) and also got the value for hItemHandle. It was 329510, which is 50726 in hex, which is the value "MDIClient" which is beneath the main node in Spy++ for my program. So I'm guessing this is getting held up by something to do with MDI windows (I know very little about them except what they are). I'll be looking around some more now since I have more to look for. – Sentient Apr 03 '12 at 16:59
  • Yes the MDI client window is the container for your MDI children. It's owned and manager by your MDI form. It's identified as `MainForm.ClientHandle` (I think). I guess this all happens when you have no MDI children showing and press F1. At the very least you could handle `WM_HELP` in your main form and detect when the message is being sent to the MDI client. – David Heffernan Apr 03 '12 at 17:02
  • @DavidHeffernan That could work.. I wouldn't really know how to do it, but I think it seems far from ideal. I don't really see why Delphi has this behavior. I was able to reproduce on a new project, and there the main form won't trigger any sort of help if the form is a MDI parent, but change back to fsNormal and it will trigger fine. – Sentient Apr 03 '12 at 22:26
  • It's not to hard (I think). See my answer which should do what you need assuming I have understood correctly. – David Heffernan Apr 03 '12 at 22:41

1 Answers1

6

According to your comments, the WM_HELP message is being targetted at your MDI client window. And since that is not a VCL control it does not respond to the WM_HELP message. You can deal with the problem by intercepting the message and asking the main form to handle it:

type
  TMainForm = class(TForm)
  protected
    procedure WMHelp(var Message: TWMHelp); message WM_HELP;
  end;
....
procedure TMainForm.WMHelp(var Message: TWMHelp);
begin
  if (Message.HelpInfo.iContextType=HELPINFO_WINDOW) 
  and (Message.HelpInfo.hItemHandle=ClientHandle) then 
    Message.HelpInfo.hItemHandle := Handle;
  inherited;
end;

If you want to be even more defensive you could write it like this:

  if (Message.HelpInfo.iContextType=HELPINFO_WINDOW) 
  and (FindControl(Message.HelpInfo.hItemHandle)=nil) then 
    Message.HelpInfo.hItemHandle := Handle;

I've just had a look at my own MDI application and I can see that I have similar code to deal with this exact issue. If it hadn't been written over 10 years ago I might have remembered sooner!

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • Awesome, thanks a lot for all your help! I had to make a small change to your code, I added: `with Message.HelpInfo{$IFNDEF CLR}^{$ENDIF} do` because the compiler didn't like the iContextType, I got that from what VCL.Forms had in it's WMHelp. (And then took out Message.HelpInfo from the second part of the and.) – Sentient Apr 03 '12 at 23:04