A rather common question on StackOverflow, the Delphi newsgroups and elsewhere is how to display a drop down menu when the user presses a button.

There are many proposed solutions and even something built into newer versions of Delphi (Which doesn’t work for me for some reason.)

Here is mine (which is based on this answer on StackOverflow):

First, I create a helper class based on TComponent. It links the button (which can be TButton or TBitBtn or anything else derived from TCustomButton) to the popup menu and hooks its OnClick event. To access the OnClick event, which is protected in TCustomButton, we need to cast it to TCustomButtonHack. The OnClick event then displays the popup menu. For convenience I set the helper class’s parent to the button, so it automatically gets freed when the button does get freed.

type TButtonPopupMenuLink = class(TComponent) private FBtn: TCustomButton; FMenu: TPopupMenu; FLastClose: DWORD; public constructor Create(_btn: TCustomButton; _pm: TPopupMenu); procedure doOnButtonClick(_Sender: TObject); end; { TButtonPopupMenuLink } type TCustomButtonHack = class(TCustomButton) end; constructor TButtonPopupMenuLink.Create(_btn: TCustomButton; _pm: TPopupMenu); begin inherited Create(_btn); FBtn := _btn; FMenu := _pm; FMenu.PopupComponent := FBtn; FBtn.OnClick := Self.doOnButtonClick; end; procedure TButtonPopupMenuLink.doOnButtonClick(_Sender: TObject); var Pt: TPoint; begin if GetTickCount - FLastClose > 100 then begin Pt := FBtn.ClientToScreen(Point(0, FBtn.ClientHeight)); FMenu.Popup(Pt.X, Pt.Y); { Note: PopupMenu.Popup does not return until the menu is closed } FLastClose := GetTickCount; end; end;

And just for some more convenience I add a procedure that just creates that helper class, so I don’t have to expose the class through the unit’s interface but only that procedure:

procedure TButton_AddDropdownMenu(_btn: TCustomButton; _pm: TPopupMenu); begin TButtonPopupMenuLink.Create(_btn, _pm); end;

To use it I call that procedure from the form’s constructor:

constructor TMyForm.Create(_Owner: TComponent); begin inherited Create; // other stuff TButton_AddDropdownMenu(b_MenuButton, pm_MenuButton); end;

I have put that code into u_dzVclUtils, which is part of my dzlib library.