Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

TPopupMenu retains max width, even after Items.clear

How can you reset the max width for a PopupMenu's items list?

Say i.e you add a few TMenuItems at runtime to a popupmenu:

item1: [xxxxxxxxxxxxxxxxxxx]
item2: [xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx]

The menu automatically adjusts the size to fit the largest item. But then you do Items.Clear and add a new item:

item1: [xxxxxxxxxxxx                    ]

It ends up like that, with a large empty space after the caption.

Is there any workaround besides re-creating the popupmenu?

Here the code for reproducing this anomaly:

procedure TForm1.Button1Click(Sender: TObject);
var
  t: TMenuItem;
begin
  t := TMenuItem.Create(PopupMenu1);
  t.Caption := 'largelargelargelargelargelarge';
  PopupMenu1.Items.Add(t);
  PopupMenu1.Popup(200, 200);
end;

procedure TForm1.Button2Click(Sender: TObject);
var 
  t: TMenuItem;
begin
  PopupMenu1.Items.Clear;
  t := TMenuItem.Create(PopupMenu1);
  t.Caption := 'short';
  PopupMenu1.Items.Add(t);
  PopupMenu1.Popup(200, 200);
end;
like image 404
hikari Avatar asked Oct 18 '14 02:10

hikari


1 Answers

tl,dr: Attach an ImageList.


If the menu items could get send a WM_MEASUREITEM message, then the width would be recalculated.

Setting the OwnerDraw property to True achieves that, which is the first solution. But for older Delphi versions, this will result in non-default and non-styled drawing of the menu items. That is not desirable.

Fortunately, TMenu has a extraordinary way of telling whether the menu (items) is (are) owner drawn:

function TMenu.IsOwnerDraw: Boolean;
begin
  Result := OwnerDraw or (Images <> nil);
end;

Thus setting the Images property to an existing ImageList will achieve the same. Note that there need not be images in the ImageList. And if there are images in it, you do not have to use them and let the ImageIndex be -1 for the menu items. Of course an ImageList with images will do just fine too.

like image 92
NGLN Avatar answered Oct 23 '22 12:10

NGLN