Avatar of efz
efz
Flag for United States of America asked on

FireMonkey - Adding Menu Items At Run Time

Hello Valued Experts,

For years I’ve used a few lines of code to maintain a history list at the bottom of the file menu of the last few files opened. I’m converting a Delphi program to FireMonkey and I’m discovering that the File menu’s InsertObject method causes a “List index out of bounds” error.

This is the line:

mnuFile.InsertObject(Idx1,Item);

Idx1 is 4 and there are 6 items in the File menu, so it wouldn’t seem the Idx1 variable is out of bounds.

If I change the Idx1 value to 1 I don’t get the error, but neither does the newly created menu item show up on the File menu.

Experimenting, I tried using AddObject(Item) and while I don’t get the error, the menu item doesn’t appear at the bottom of the File menu either.

I’m stuck. Any insight would be greatly appreciated.

Thanks in advance.
DelphiProgramming Languages-Other

Avatar of undefined
Last Comment
efz

8/22/2022 - Mon
Ferruccio Accalai

For what you're saying I guess that you have an index value different than the real one, like if you're considering some items that are not already inserted (but you are instead sure of yes). How do you retrieve your idx1 value?
efz

ASKER
Thanks Ferruccio68,

The entire section of code is not that long. Here it is. I included some comments after the code to better explain what’s happening.

Idx1 := N1.Index+1;
If History.Count > 0 then
  begin
  For Pos := 0 to History.Count - 1 do
    begin
    Item := TMenuItem.Create(mnuFile);
    Item.Text := IntToStr(Pos + 1) + ' ' + History[Pos];
    Item.OnClick := ReOpenClick;
    mnuFile.InsertObject(Idx1,Item);
    end;
  end;

Open in new window

1. N1 is a TMenuItem that is a bar separator; Idx1 is an integer.  N1 is used to mark the dividing line between the File menu and the history list. Idx1 is supposed to be the zero-based position of the bar separator in the File menu. The File menu looks like this:

    New
    Open
    Save
    Save As
    Print
    -
    Exit

The value of N1.Index at run time is 5 which seems correct.

2. If there are history items (a TStringList of previously Opened files), then insert the file names as menu items.

3. The InsertObject line is the one that craps out as explained in the original question.
Ferruccio Accalai

Your code seems right. Have you tested the mnuFile items count to see if it's ok in that moment? There are a bit of bugs about the InsertObject method that are under investigation on Embarcadero QualityCentral.
Maybe this is another one of those.
Your help has saved me hundreds of hours of internet surfing.
fblack61
efz

ASKER
That’s where I’m running into a little trouble. Delphi menus had arrays of items. A menu had an Insert method and you could ask for an Item.Count to determine the size of the array. FireMonkey menus are different. There is no array of Items and there is no Insert method. Instead FireMonkey menus have InsertObject and AddObject, but these commands don’t seem to have anything to do with manipulating the subitems in the menu. That’s another thing, when I ask for the ChildrenCount of the TMenuItem in question (File) it gives a value of 2 when in fact there are 7 items in the menu. Evidently the menu’s subitems (New, Open, etc.) are not considered children of the File menu, although this contrary to what you see in the Structure view where New, Open etc. are shown as children of File. Of course, that accounts for the out of bounds error because I’m trying to InsertObject at position 6 but the ChildrenCount is 2. I can’t make sense of this, can you?
Ferruccio Accalai

The structure is different from the knowed Windows , maybe because the cross platform capability and compatibility.
Anyway it seems that any Top MenuItem is considered like a TMainMenu's child and maybe any of these children are called subitems or something else, as I'd expect.

So, saying that a File menu could be the first TMenuItem of a TMainMenu and for this have a Child index = 0, from my head, I should try mnuFile.Child[0].InsertObject(Idx1,Item)
( or maybe mnuFile.Children[0].InsertObject(Idx1,Item), I don't know about the FireMonkey syntax)

It's just I guess, I don't have FireMonkey
ASKER CERTIFIED SOLUTION
efz

Log in or sign up to see answer
Become an EE member today7-DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform
Sign up - Free for 7 days
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.
Not exactly the question you had in mind?
Sign up for an EE membership and get your own personalized solution. With an EE membership, you can ask unlimited troubleshooting, research, or opinion questions.
ask a question
Ferruccio Accalai

Wow, I was quite next to the solution!

From your link:

uses
  Fmx.Platform;
 
mnuFile.Children[0].InsertObject(Idx1,Item);
if IsHandleValid(mnuFile.Handle) then
  Platform.UpdateMenuItem(mnuFile);


My guess

try mnuFile.Child[0].InsertObject(Idx1,Item)
( or maybe mnuFile.Children[0].InsertObject(Idx1,Item),


Lol, I'm ready to start with FireMonkey :)
Get an unlimited membership to EE for less than $4 a week.
Unlimited question asking, solutions, articles and more.
efz

ASKER
A final point of clarification. After further discussion with an Embarcadero team member, it would seem that the InsertObject and AddObject methods do not work in the context of FireMonkey's TMenuBar, although they do when used with TMainMenu.
efz

ASKER
I received the correct answer from an Embarcadero technician/team member who has first hand knowledge of this issue and was able to test his solution.