Lazarus

Programming => LCL => Topic started by: fatmonk on March 02, 2021, 12:55:36 pm

Title: [SOLVED] Copy the contents of a popup menu into a submenu of another popup menu
Post by: fatmonk on March 02, 2021, 12:55:36 pm
I have two popup menus defined: pumMain and pumPresets.

These are accessed by clicking two different buttions in my application.

I would like to make the contents of pumPresets available as a submenu of pumMain without duplicating the menu.

I see that TMenu.Assign and TMenuItem.Assign can be used to to copy menus and items, but is there a way to 'embed' pumPresets as a submenu of pumMain?

At the moment I have just added an OnClick to the 'Presets' option in the main menu which opens the pumPresets popup menu. This works, but the 'Presets' option in the main menu doesn;t have the triangel to the right and the alignment of the Presets menu isn;t the same as if it were a true submenu...

Any ideas?

-FM
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: jamie on March 02, 2021, 10:46:41 pm
The menus have an Owner draw option.. You can draw the little arrow if you wish during the drawing on the menu item..
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: fatmonk on March 03, 2021, 02:14:41 pm
That would solve the missing arrow issue, but the alignment and the fact that the previous menu closes when opening the second popup looks odd... maybe I need to rethink this whole approach.

-FM
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: lucamar on March 03, 2021, 09:38:50 pm
Any reason why you can't just assign the base menuitem of the popup as the direct child of the mainmenu item you want? Or traversing the popup items and assigning/adding to an item in the main menu submenu?

If you don't know what I'm talking about, tell me and I'll try to make a small example tomorrow (it's a little late here-now).
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: howardpc on March 04, 2021, 10:27:31 am
You could try this.
In a new Lazarus project, double-click the empty form to generate an OnCreate handler.

Then copy the following code from the "private" declaration onwards, and run it.
Code: Pascal  [Select][+][-]
  1. unit uMain;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, Forms, Controls, Dialogs, Menus, StdCtrls;
  9.  
  10. type
  11.   TForm1 = class(TForm)
  12.     procedure FormCreate(Sender: TObject);
  13.   private
  14.     pumMain: TPopupMenu;
  15.     pumPresets: TPopupMenu;
  16.     mainButton: TButton;
  17.     presetButton: TButton;
  18.     submenuButton: TButton;
  19.     procedure MainButtonClick(Sender: TObject);
  20.     procedure PresetButtonClick(Sender: TObject);
  21.     procedure PresetOnClick(Sender: TObject);
  22.     procedure SubmenuButtonClick(Sender: TObject);
  23.   end;
  24.  
  25. var
  26.   Form1: TForm1;
  27.  
  28. implementation
  29.  
  30. {$R *.lfm}
  31.  
  32. procedure TForm1.FormCreate(Sender: TObject);
  33. begin
  34.   Caption := 'Menu copying example';
  35.  
  36.   pumMain := TPopupMenu.Create(Self);
  37.   pumMain.Items.Add(NewItem('Main 1', 0, False, True, Nil, 0, ''));
  38.   pumMain.Items.Add(NewItem('Main 2', 0, False, True, Nil, 0, ''));
  39.   pumMain.Items.Add(NewItem('Main 3', 0, False, True, Nil, 0, ''));
  40.  
  41.   pumPresets := TPopupMenu.Create(Self);
  42.   pumPresets.Items.Add(NewItem('Presets 1', 0, False, True, @PresetOnClick, 0, ''));
  43.   pumPresets.Items.Add(NewItem('Presets 2', 0, False, True, @PresetOnClick, 0, ''));
  44.   pumPresets.Items.Add(NewItem('Presets 3', 0, False, True, @PresetOnClick, 0, ''));
  45.  
  46.   mainButton := TButton.Create(Self);
  47.   with mainButton do
  48.     begin
  49.       AutoSize := True;
  50.       Caption := 'Popup main';
  51.       OnClick := @MainButtonClick;
  52.       BorderSpacing.Around := 20;
  53.       AnchorSideTop.Control := Self;
  54.       AnchorSideLeft.Control := Self;
  55.       Parent := Self;
  56.     end;
  57.  
  58.   presetButton := TButton.Create(Self);
  59.   with presetButton do
  60.     begin
  61.       AutoSize := True;
  62.       Caption := 'Popup preset';
  63.       OnClick := @PresetButtonClick;
  64.       BorderSpacing.Around := 20;
  65.       AnchorSideLeft.Control := Self;
  66.       AnchorSideTop.Control := mainButton;
  67.       AnchorSideTop.Side := asrBottom;
  68.       Parent := Self;
  69.     end;
  70.  
  71.   submenuButton := TButton.Create(Self);
  72.   with submenuButton do
  73.     begin
  74.       AutoSize := True;
  75.       Caption := 'Add preset to main';
  76.       OnClick := @SubmenuButtonClick;
  77.       BorderSpacing.Around := 20;
  78.       AnchorSideLeft.Control := Self;
  79.       AnchorSideTop.Control := presetButton;
  80.       AnchorSideTop.Side := asrBottom;
  81.       Parent := Self;
  82.     end;
  83. end;
  84.  
  85. procedure TForm1.MainButtonClick(Sender: TObject);
  86. begin
  87.   pumMain.PopUp;
  88. end;
  89.  
  90. procedure TForm1.PresetButtonClick(Sender: TObject);
  91. begin
  92.   pumPresets.PopUp;
  93. end;
  94.  
  95. procedure TForm1.PresetOnClick(Sender: TObject);
  96. begin
  97.   if Sender is TMenuItem then
  98.     ShowMessage('You clicked menu captioned '+TMenuItem(Sender).Caption);
  99. end;
  100.  
  101. procedure TForm1.SubmenuButtonClick(Sender: TObject);
  102. var
  103.   mi, smi: TMenuItem;
  104.   i: Integer;
  105. begin
  106.   mi := TMenuItem.Create(pumMain);
  107.   pumMain.Items[2].Insert(0, mi);
  108.   mi.Caption := 'Added Presets';
  109.   for i := 0 to pumPresets.Items.Count-1 do
  110.     begin
  111.       smi := TMenuItem.Create(pumMain);
  112.       smi.Caption := pumPresets.Items[i].Caption;
  113.       smi.OnClick := pumPresets.Items[i].OnClick;
  114.       mi.Add(smi);
  115.     end;
  116.   submenuButton.Enabled := False;
  117. end;
  118.  
  119. end.
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: fatmonk on March 11, 2021, 04:39:12 pm
assign the base menuitem of the popup as the direct child of the mainmenu item you want

Thats sounds like exactlywhat I want to do (except that both are actually popup menus rather than one being a MainMenu), but I have no idea how to do that.

I was going to knock up a demo project but haven't had a chance yet.. if you can give any pointers that woudl be useful, otherwise I'll put that demo together and maybe you can point out how to do it with that.

Thanks,

-FM
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: lucamar on March 11, 2021, 05:04:22 pm
All menus, whether PopUp of MainMenu, have a property Items which is itself a TMenuItem, so suppossing you have an item in some menu called, say. SubItem and a popup called EditPopUp, you just have to do:
Code: Pascal  [Select][+][-]
  1. SubItem.Items.Assign(EditPopUp.Items);
Note that I've not tested it but it should work. You might have to change some properties, perhaps, but that will be evident after the initial testing.

HTH!
Title: Re: Copy the contents of a popup menu into a submenu of another popup menu
Post by: fatmonk on March 18, 2021, 01:11:55 pm
Hi Lucamar,

Thank for the pointer.. after a bit of playing around I figured it out.

The correct syntax is:

Code: Pascal  [Select][+][-]
  1.   miPresets.Assign(pumPresets.Items);

where miPresets is the appropriate TMenuItem in the main TPopupMenu and pumPresets is the second TPopUpMenu that I want to open when the menu item in the main popup menu is clicked.

The
Code: Pascal  [Select][+][-]
  1. assign
, however, removes the existing Caption for the MenuItem, so I also needed to re-assign that with:

Code: Pascal  [Select][+][-]
  1.   miPresets.Caption:='Presets';  

All good now, though  :D

-FM



Title: Re: [SOLVED] Copy the contents of a popup menu into a submenu of another popup menu
Post by: lucamar on March 18, 2021, 02:38:11 pm
Yeah, sorry; I made an error because I used a top menu item in a main menu for the tests :-[

Though it should have worked also for a pop up, leaving the "parent" item intact ... looks like I've got to test more deeply how these things work :-X
TinyPortal © 2005-2018