Search code examples
delphivcldelphi-xe4windows-messages

Capture Help Button Click with Custom VCL Style


I have a VCL form that is set for bsDialog with biHelp enabled ("?" icon in application bar). The application is also using a custom VCL Style (Aqua Light Slate).

However I cannot get the WMNCLBUTTONDOWN Windows Message to appear when I click the "?" button. It only works if the VCL Style of the application is changed back to Windows (Default).

procedure TMainFrm.WMNCLButtonDown(var Msg: TWMNCLButtonDown);
begin
  if Msg.HitTest = HTHELP then
  begin
    OutputDebugString('Help button down');
    Msg.Result := 0;
  end
  else
    inherited;
end;

procedure TMainFrm.WMNCLButtonUp(var Msg: TWMNCLButtonUp);
begin
  if Msg.HitTest = HTHELP then
  begin
    OutputDebugString('Help button up');
    Msg.Result := 0;
  end
  else
    inherited;
end;

Is there a way to get these events to fire with a custom VCL style?


Solution

  • The form style hook handles that message:

    TFormStyleHook = class(TMouseTrackControlStyleHook)
    ....
      procedure WMNCLButtonUp(var Message: TWMNCHitMessage); message WM_NCLBUTTONUP;
    end;
    

    The implementation includes this

    else if (Message.HitTest = HTHELP) and (biHelp in Form.BorderIcons) then
      Help;
    

    This calls the virtual Help method of the form style hook. That is implemented like this:

    procedure TFormStyleHook.Help;
    begin
      SendMessage(Handle, WM_SYSCOMMAND, SC_CONTEXTHELP, 0)
    end;
    

    So you could simply listen for WM_SYSCOMMAND and test wParam for SC_CONTEXTHELP. Like this:

    type
      TMainFrm = class(TForm)
      protected
        procedure WMSysCommand(var Message: TWMSysCommand); message WM_SYSCOMMAND;
      end;
    ....
    procedure TMainFrm.WMSysCommand(var Message: TWMSysCommand);
    begin
      if Message.CmdType = SC_CONTEXTHELP then begin
        OutputDebugString('Help requested');
        Message.Result := 0;
      end else begin
        inherited;
      end;
    end;