Page 1 of 1
Forum

Welcome to the Tweaking4All community forums!
When participating, please keep the Forum Rules in mind!

Topics for particular software or systems: Start your topic link with the name of the application or system.
For example “MacOS X – Your question“, or “MS Word – Your Tip or Trick“.

Please note that switching to another language when reading a post will not bring you to the same post, in Dutch, as there is no translation for that post!



Share:
Notifications
Clear all

[Solved] Lazarus - Windows - Catching the Alt key for show/hide mainmenu

1 Posts
1 Users
0 Reactions
2,550 Views
 Hans
(@hans)
Famed Member Admin
Joined: 12 years ago
Posts: 2859
Topic starter  

These days, most Windows applications seem to hide their main menu, and only reveal it after pressing the "Alt" key. Of course I wanted to implement this for one of my applications as well (Rename My TV series). Took me a while to figure it out and it's still not quite perfect.

The idea;
By default the main menu is not visible. Pressing the Alt key toggles it visible or not visible.
This method does just that, with one downside. Pressing Alt reveals the menu, but since it get's focus, you'll need to press the Alt key 2 or 3 times before it disappears again (the menu is doing stuff with the Alt key as well).

Step 1: Show/Hide the menu

On start I hide the menu as such:

self.Menu:=nil;

This effectively will disconnect the mainmenu from the form.
Making it visible is as simple as (assuming your menu is called MainMenu1):

self.Menu:=MainMenu1; 

Step 2: Catching that Alt Key

This appears to be a little bit more complex and NOT CROSSPLATFORM!
You'll need to add the unit "windows" to your "uses" clause.

Add the following to the "private" section of your form:

procedure KeyMessage(Msg: LongWord; wParam:longint);

Add this right after the "implementation" keyword:

var
  AltKeyHook: HHOOK;
function MessageHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
var
  Msg: LCLType.PMsg absolute lParam;
begin
  if nCode >= 0 then
    case Msg^.message of
      WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_CHAR, WM_SYSCHAR:
        Form1.KeyMessage(Msg^.message, Msg^.wParam); // make sure to use the right form variable here!
    end;
  Result := CallNextHookEx(AltKeyHook, nCode, wParam, lParam);
end;
procedure TForm1.KeyMessage(Msg: LongWord; wParam:longint);
begin
  if (Msg=WM_SYSKEYDOWN) and (wParam=18{=Alt key}) then
    begin
      if self.Menu=nil then// Toggle menu, assuming your MainMenu is called Mainmenu1
        self.Menu:=MainMenu
      else
        self.Menu:=nil;
    end;
end;  

In the FormCreate event add:

  AltKeyHook := SetWindowsHookEx(WH_GETMESSAGE, @MessageHookProc, 0, MainThreadID);

In the FormDestroy event add:

  if AltKeyHook <> 0 then
  begin
    UnhookWindowsHookEx(AltKeyHook);
    AltKeyHook := 0;
  end;

And that's it ... 

Keep in mind, in the Keymessage function, you can also catch these "Msg" values: WM_KEYDOWN, WM_KEYUP, WM_SYSKEYDOWN, WM_SYSKEYUP, WM_CHAR, and WM_SYSCHAR. The "wParam" value holds the character or key code eg. IntToStr(wParam) of Chr(wParam).


   
ReplyQuote
Share: