A "Button with a Drop Down Context Menu" appears as a normal button with an additional down arrow on the right side of the button.
Clicking the "popup button" acts as, well, clicking the button.
Clicking the arrow display a popup menu with an additional set of options.
You will usually find such buttons on toolbars. Delphi IDE's Run button hosts a down arrow - allowing you to select what project in a project group to start. Clicking on the run buttonn directly starts the currently active project.
Another example is the "Send/Receive" button on the toolbar of Outlook Express email client.
There are quite a few (even free with source) third-party Delphi components implementing the idea of a "drop down button".
Let's see how to quickly create such a button using Delphi's TFrame object and two "ordinary" TButton controls, for a test :)
A Dirty implementation of a "Drop Down Button"
The easiest way of mimicking a "drop down button" is to actually have two buttons. The "left" one will act as a "standard" button. The right one will display a down arrow.Clicking on the right button will display a popup menu with an additional set of options to be executed.
Here are the steps to implement a drop down button with a demo application:
- Create a new Delphi project containing one form.
- Add a Frame to the project by selecting File - New - Other - Delphi Files - Frame from the IDE's main menu.
- On the frame add two buttons.
- Let the left one be named "MainButton". Set the Align property to alClient.
- Let the right one be named "MenuButton". Set the Align property to alLeft.
- Save the unit as "UnitButtonMenu". Let the name of the frame be "ButtonMenu".
Since, by design, a popup menu assigned to a Delphi control, gets displayed when the user clicks the right button over the component, we need to suppress the display of the frame's context menu. This is done using the OnContextPopup event of the frame.
Here's the initial source code of the frame ("UnitButtonMenu" unit):
unit UnitButtonMenu;What's needs to be implemented is the actual display of the popup menu when the "arrow button" is clicked.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, Menus;
type
TButtonMenu = class(TFrame)
MainButton: TButton;
MenuButton: TButton;
procedure FrameContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean) ;
private
{ Private declarations }
public
{ Public declarations }
end;
implementation
{$R *.dfm}
procedure TButtonMenu.FrameContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean) ;
begin
//suppress the default context menu
Handled := true;
end;
end.
Create the handler for the OnClick event of the "MenuButton" button for the frame:
procedure TButtonMenu.MenuButtonClick(Sender: TObject) ;
var
popupPoint : TPoint;
begin
if Assigned(PopupMenu) then
begin
popupPoint.X := MenuButton.Left + (MenuButton.Width DIV 2) ;
popupPoint.Y := MenuButton.Top + (MenuButton.Height DIV 2) ;
popupPoint := ClientToScreen(popupPoint) ;
//display the popup in the center of the "menu button"
PopupMenu.Popup(popupPoint.X, popupPoint.Y) ;
end;
end;
When the "arrow button" is clicked we display the popup menu assigned to the frame object - as if the frame was right-clicked.
Note that the actual popup menu used is not a part of the frame. You will create a popup menu and its items on the form where the "ButtonMenu" will be hosted.
Using the "Drop Down Button"
On the form drop the "ButtonMenu" frame. You do that by dragging the "Frames" items from the Standard group on the component palette.When you "drop", the "Select frame to insert" dialog box will let you select the frame to be added to the form.
Having the "ButtonMenu" frame on the form, drop one TPopupMenu on the form, also. Add items to the popup menu. Assign it to the PopupMenu property of the frame object (by default named "ButtonMenu1") on the form.
Let's say you have to menu items defined for the popup: "CloseItem" and "CloseSaveItem". Here's a sample implementation of the OnClick event handlers:
procedure TForm1.CloseItemClick(Sender: TObject) ;
begin
ShowMessage('This should close the program...') ;
end;
procedure TForm1.CloseSaveItemClick(Sender: TObject) ;
begin
ShowMessage('Save all user information and close program ...') ;
end;
Notes to note
Note that you can double-click the frame's "arrow button" at design-time. Delphi will create a non-empty event handler:procedure TForm1.ButtonMenu1MenuButtonClick(Sender: TObject) ;What's more you can change any of the properties of both the buttons directly from the form hosting the frame.
begin
//added by Delphi - display the popup menu
ButtonMenu1.MenuButtonClick(Sender) ;
//add more code here
//....
end;
You could use the TBitBtn buttons, for glyphs to be easily displayed on the buttons.
I'll leave you to your imagination. This implementation is not ideal, but does the trick :)


