MonkeySleeve
MonkeySleeve

Reputation: 37

How to apply a keyboardhook on F1 within the application

For our application we created a Online Help where customers can look up stuff about our application. They can reach this in the menus but I also wanted to make it available by pressing the F1 key where ever you are within our application(since this is mostly used for Help within other applications).

I tried using the RegisterHotKey function but as it turns out, this registers the hotkey system wide. I only want it to open our Online Help when you are within our application.

So i tried to setup a Keyboard hook but this also seems to apply it system wide. Is there a way to make sure that pressing the F1 key within the application will open it, but not when you don't have the application focused?

Code what I tried:

procedure WMHotKey(var Msg: TWMHotKey); message WM_HOTKEY;

procedure TZZ_Main_Form.WMHotKey(var Msg: TWMHotKey);
begin
  if Msg.HotKey = HotKeyIDF1 then btOnlineHelpClick(nil);
end;

Within the FormCreate and FormDestroy:

RegisterHotKey(Handle, HotKeyIDF1, 0, VK_F1);
UnRegisterHotKey(Handle, HotKeyIDF1);

Regarding the keyboard hook, what i tried:

  hkHook := SetWindowsHookEx(WH_KEYBOARD,@KeyboardProc,hInstance,GetCurrentThreadID());

function KeyboardProc(Code, wParam, lParam: Integer): Integer;
var
  url: String;
  ShellInfo: TShellExecuteInfo;
begin
  try
    case wParam of
      VK_F1:
      begin
        url := 'ourOnlineHelpLink'
        if url <> '' then
        begin
          FillChar( ShellInfo, SizeOf( TShellExecuteInfo ), 0 );
          ShellInfo.cbSize := SizeOf( TShellExecuteInfo );
          ShellInfo.fMask := SEE_MASK_NOCLOSEPROCESS or SEE_MASK_FLAG_NO_UI or
                         SEE_MASK_FLAG_DDEWAIT;
          ShellInfo.Wnd := HWnd_Desktop;
          ShellInfo.lpVerb := 'OPEN';
          ShellInfo.lpFile := PChar( url );
          ShellInfo.lpParameters := nil;
          ShellInfo.lpDirectory := nil;
          ShellInfo.nShow := sw_ShowNormal;

          ShellExecuteEx( @ShellInfo );
        end;
      end;
    end;
  finally
     Result := -1;
  end;
end;

Upvotes: 1

Views: 664

Answers (2)

SilverWarior
SilverWarior

Reputation: 8331

If you want to show Online Help to you application then you would rather use existing help support using OnHelp events as Ondrej Kelle already recomended in his comment.

Using existing help system also gives you another advantage. And that is that for each of your controlls you can set specific values for HelpContext and HelpKeyword meaning that instead of opening Online Help start page you can already navigate to the relevant help page which makes using of provided help system much easier to your application users.

By the way if you don't want to use HTMLHelp systey for online help using OnHelp events you can still easily implement your own system for displaying help.

Upvotes: 2

Ken White
Ken White

Reputation: 125669

You can intercept the F1 application-wide by using TApplicationEvents.OnHelp.

Drop the component on your main form, or in a datamodule that is created before your main form. Double-click the OnHelp event on its events tab, and add code similar to the following (the parameter types changed after Delphi 2007, so I've included support for both):

// Delphi 2007 and earlier
{$IFDEF VER185}
function TMainForm.ApplicationEvents1Help(Command: Word; Data: Integer;
  var CallHelp: Boolean): Boolean;
begin
  CallHelp := False;
  // Call your own procedure to implement help as you'd like
  Result := True;
end;
{$ELSE Greater than D2007}
function TMainForm.ApplicationEvents1Help(Command: Word; Data: NativeInt;
  var CallHelp: Boolean): Boolean;
begin
  CallHelp := False;
  // Call your own procedure to implement help as you'd like
  Result := True;
end;
{$ENDIF}

Upvotes: 2

Related Questions