delphifiremonkeydelphi-10.2-tokyo

Dynamically created FireMonkey TPopupMenu doesn't Pop Up


Start a new Multi-Device application and place a button on it. Declare a member variable in the form POP: TPopupMenu. Double-click the button and insert the following code in the event:

var
  MI    : TMenuItem;
  I     : Cardinal;
begin
  FreeAndNIL(POP); // POP is a member variable of the form
  POP:=TPopupMenu.Create(Self);
  FOR I:=1 TO 10 DO BEGIN
    MI:=TMenuItem.Create(POP);
    MI.Text:=IntToStr(I);
    MI.OnClick:=Button1Click;
    POP.AddObject(MI)
  END;
  POP.Popup(100,100)
end;

(I know that assigning Button1Click to OnClick will lead to recursive calls, but I have included it to preempt suggestions that there are no events associated with the TMenuItem).

It should pop up a menu when you click the button, but it doesn't (actually, it kinda does - it pops up a 0-pixel width popup menu, which you can verify in that the button doesn't "glow" when you move the mouse over it, until you have clicked somewhere to "close" this (unseen) popup menu).

I can see (if I trace into POP.PopUp) that it transfers the TMenuItems into a new popup menu type, and starts calculating the size of the popup. But when it iterates over the items, it skips the part that handles the width of the menu items' texts (there's no "TextObject", ie. it's NIL).

If I do the similar code in VCL it works fine, so what is different in FMX that makes this not work? Do I need to "commit" the TPopupMenu changes or what?


Solution

  • In the FMX framework, a TPopupMenu needs to have either the PopupComponent or the Parent property set, to become visible when called. Since you want to create a popup menu that is not tied to any specific control as a that controls popup menu (made visible with a right-click), you must assign its Parent property:

    POP.Parent := Self; // The form in your example
    

    Note that the coordinates passed to POP.Popup() are screen coordinates despite the parent setting.