Bookstore

Recent

Author Topic: Show Popupmenu above button  (Read 3573 times)

Ericktux

  • Full Member
  • ***
  • Posts: 198
Show Popupmenu above button
« on: June 29, 2017, 08:54:18 am »
Good day my friends, how can i show popupmenu over button ?  :(

Handoko

  • Hero Member
  • *****
  • Posts: 3434
  • My goal: build my own game engine using Lazarus
Re: Show Popupmenu above button
« Reply #1 on: June 29, 2017, 10:10:40 am »
You cannot control how popup shows up, the position and size depend on the amount of the popup items.

Except you write your own custom-made popup component. Or creating a form that behaves like a popup. Try my custompopup.zip:

Code: Pascal  [Select]
  1. unit unit2;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Forms, Controls, StdCtrls;
  9.  
  10. type
  11.  
  12.   { TfrmPopup }
  13.  
  14.   TfrmPopup = class(TForm)
  15.     ListBox1: TListBox;
  16.     procedure ListBox1DblClick(Sender: TObject);
  17.     procedure ListBox1KeyPress(Sender: TObject; var Key: char);
  18.   public
  19.     Selected: Integer; // -1 means cancelled
  20.   end;
  21.  
  22. var
  23.   frmPopup: TfrmPopup;
  24.  
  25. implementation
  26.  
  27. {$R *.lfm}
  28.  
  29. { TfrmPopup }
  30.  
  31. procedure TfrmPopup.ListBox1KeyPress(Sender: TObject; var Key: char);
  32. begin
  33.   case Key of
  34.     #27: begin
  35.          Selected := -1;
  36.          Close;
  37.          end;
  38.     #13: begin
  39.          Selected := ListBox1.ItemIndex;
  40.          Close;
  41.          end;
  42.   end;
  43. end;
  44.  
  45. procedure TfrmPopup.ListBox1DblClick(Sender: TObject);
  46. const
  47.   C: Char = #13;
  48. begin
  49.   ListBox1KeyPress(Self, C);
  50. end;
  51.  
  52. end.

I tested the code on Ubuntu Mate. The appearance may be different on Windows.

=== edit ===
Actually, we can control the X, Y positions of a TPopupMenu to show up. But the problem is, if the list contains a lot of items, the position will be changed automatically to able to show on your screen. Here are the calculations:
Popup.Top := Button1.Top + Button1.Height + Form1.Top - Popup.Height;
Popup.Left := Button1.Left + Form1.Left;     
« Last Edit: June 29, 2017, 10:44:19 am by Handoko »

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 216
Re: Show Popupmenu above button
« Reply #2 on: June 29, 2017, 11:06:42 am »
You cannot control how popup shows up

At least with WinAPI you can tell the popup menu where to show. See https://msdn.microsoft.com/de-de/library/windows/desktop/ms648003(v=vs.85).aspx.

Handoko

  • Hero Member
  • *****
  • Posts: 3434
  • My goal: build my own game engine using Lazarus
Re: Show Popupmenu above button
« Reply #3 on: June 29, 2017, 11:17:07 am »
TPopupMenu has Popup(X, Y: Integer). The problem is we can not be sure to know the TPopup.Height, which is needed to calculate the exact position. See the calculation I provided on my previous post.

Ondrej Pokorny

  • Full Member
  • ***
  • Posts: 216
Re: Show Popupmenu above button
« Reply #4 on: June 29, 2017, 11:36:13 am »
On Windows you can do everything. Popup(X, Y: Integer) calls TrackPopupMenu/TrackPopupMenuEx as well. So you only need to write your own PopupEx function with custom parameters.

You can also calculate the menu height. (That is more advanced.)

rvk

  • Hero Member
  • *****
  • Posts: 3943
Re: Show Popupmenu above button
« Reply #5 on: June 29, 2017, 11:55:26 am »
On Windows you can do everything. Popup(X, Y: Integer) calls TrackPopupMenu/TrackPopupMenuEx as well. So you only need to write your own PopupEx function with custom parameters.
Yep, i.e. something like this:
(no need for height calculations with TPM_BOTTOMALIGN)

Code: Pascal  [Select]
  1. uses Windows, Types;
  2.  
  3. procedure TForm1.Button1Click(Sender: TObject);
  4. const
  5.   Flags: array[boolean, TPopupAlignment] of word =
  6.     ((TPM_LEFTALIGN, TPM_RIGHTALIGN, TPM_CENTERALIGN),
  7.     (TPM_RIGHTALIGN, TPM_LEFTALIGN, TPM_CENTERALIGN));
  8.   Buttons: array[TTrackButton] of word = (TPM_RIGHTBUTTON, TPM_LEFTBUTTON);
  9. var
  10.   AFlags: integer;
  11.   P: TPoint;
  12. begin
  13.   AFlags := Flags[UseRightToLeftAlignment, PopupMenu1.Alignment] or
  14.     Buttons[PopupMenu1.TrackButton] or TPM_BOTTOMALIGN;
  15.   P := Button1.ClientToScreen(Types.Point(0, 0));
  16.   TrackPopupMenu(PopupMenu1.Items.Handle, AFlags, P.X, P.Y, 0, Button1.Handle, nil);
  17. end;

« Last Edit: June 29, 2017, 11:58:40 am by rvk »

Ericktux

  • Full Member
  • ***
  • Posts: 198
Re: Show Popupmenu above button
« Reply #6 on: June 29, 2017, 09:50:07 pm »
Thanks friends for your answers, Your codes can also be used in linux ?

rvk

  • Hero Member
  • *****
  • Posts: 3943
Re: Show Popupmenu above button
« Reply #7 on: June 29, 2017, 09:56:24 pm »
Your codes can also be used in linux ?
Nope, for linux you need to follow Handoko's instructions and calculate the height and set the x and y positions so the popup can dropdown to just above the button.
« Last Edit: June 29, 2017, 09:58:43 pm by rvk »

Ericktux

  • Full Member
  • ***
  • Posts: 198
Re: Show Popupmenu above button
« Reply #8 on: June 29, 2017, 11:38:22 pm »
hi my friends, I noticed than moving the form down The popupmenu is shown above.  ::)
But if the form moves it above the popupmenu comes down.  :)

i use this code:
Code: Pascal  [Select]
  1. procedure TForm1.Button1Click(Sender: TObject);
  2. begin
  3.     with Button1.ClientToScreen(point(0, 0)) do
  4.      PopupMenu1.Popup(X, Y);
  5. end;

I'll use it for the moment.
Thanks friends for your help  :)
« Last Edit: June 30, 2017, 12:32:19 am by Ericktux »