Recent

Author Topic: [SOLVED] Copy the contents of a popup menu into a submenu of another popup menu  (Read 2193 times)

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
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
« Last Edit: March 18, 2021, 01:12:44 pm by fatmonk »

jamie

  • Hero Member
  • *****
  • Posts: 6090
The menus have an Owner draw option.. You can draw the little arrow if you wish during the drawing on the menu item..
The only true wisdom is knowing you know nothing

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
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

lucamar

  • Hero Member
  • *****
  • Posts: 4219
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).
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

howardpc

  • Hero Member
  • *****
  • Posts: 4144
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.

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
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

lucamar

  • Hero Member
  • *****
  • Posts: 4219
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!
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

fatmonk

  • Sr. Member
  • ****
  • Posts: 252
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




lucamar

  • Hero Member
  • *****
  • Posts: 4219
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
Turbo Pascal 3 CP/M - Amstrad PCW 8256 (512 KB !!!) :P
Lazarus/FPC 2.0.8/3.0.4 & 2.0.12/3.2.0 - 32/64 bits on:
(K|L|X)Ubuntu 12..18, Windows XP, 7, 10 and various DOSes.

 

TinyPortal © 2005-2018