1. Home
  2. Computing & Technology
  3. Delphi Programming

How to Detect a TPopupMenu's OnClose (OnPopDown) Event

By Zarko Gajic, About.com

The TPopupMenu component encapsulates the properties, methods, and events of a pop-up menu. A pop-up menu appears (for a component or a form) when the user clicks on a control with the right mouse button.

TPopupMenu provides the OnPopup event that gets fired just before the pop-up menu appears.

Unfortunately, the TPopupMenu does not expose an event you can handle that will fire when the menu gets closed - either after a user has selected an item from the menu or has activated some other UI element.

What happens when a user selects an item from a popup menu is that Windows sends a WM_MENUSELECT message (with some specific parameter values) and a WM_EXITMENULOOP message to the window owning the menu. However, the window owning the menu is *not* your Delphi form - it is a tool window created and managed by the TPopupList class defined in the menus.pas unit.

To get notified when the popup menu closes, you have to extend the PopupList class by adding several new message handling options.

TPopupListEx

Here's the source of the extended PopupList class you need to add to your projects in order to be able to respond when the popup menu is closed:
unit PopupListEx;

interface

uses Controls;

const
   CM_MENU_CLOSED = CM_BASE + 1001;
   CM_ENTER_MENU_LOOP = CM_BASE + 1002;
   CM_EXIT_MENU_LOOP = CM_BASE + 1003;

implementation

uses Messages, Forms, Menus;

type
   TPopupListEx = class(TPopupList)
   protected
     procedure WndProc(var Message: TMessage) ; override;
   private
     procedure PerformMessage(cm_msg : integer; msg : TMessage) ;
   end;

{ TPopupListEx }
procedure TPopupListEx.PerformMessage(cm_msg: integer; msg : TMessage) ;
begin
   if Screen.Activeform <> nil then
     Screen.ActiveForm.Perform(cm_msg, msg.WParam, msg.LParam) ;
end;

procedure TPopupListEx.WndProc(var Message: TMessage) ;
begin
   case message.Msg of
     WM_ENTERMENULOOP: PerformMessage(CM_ENTER_MENU_LOOP, Message) ;
     WM_EXITMENULOOP : PerformMessage(CM_EXIT_MENU_LOOP, Message) ;
     WM_MENUSELECT :
     with TWMMenuSelect(Message) do
     begin
       if (Menu = 0) and (Menuflag = $FFFF) then
       begin
         PerformMessage(CM_MENU_CLOSED, Message) ;
       end;
     end;
   end;
   inherited;
end;

initialization
   Popuplist.Free; //free the "default", "old" list
   PopupList:= TPopupListEx.Create; //create the new one
   // The new PopupList will be freed by
   // finalization section of Menus unit.
end.
Here's how to use the PopupListEx unit:
  1. Drop a TPopupMenu on a Delphi form
  2. Add several menu items to the PopupMenu
  3. Include the "PopupListEx" in the uses clause
  4. Write a procedure to handle PopupListEx's messages: CM_MENU_CLOSED, CM_ENTER_MENU_LOOP and CM_EXIT_MENU_LOOP
An example implementation (download):
uses PopupListEx, ...

TForm1 = class(TForm)
...
private
   procedure CM_MenuClosed(var msg: TMessage) ; message CM_MENU_CLOSED;
   procedure CM_EnterMenuLoop(var msg: TMessage) ; message CM_ENTER_MENU_LOOP;
   procedure CM_ExitMenuLoop(var msg: TMessage) ; message CM_EXIT_MENU_LOOP;
...
implementation

procedure TForm1.CM_EnterMenuLoop(var msg: TMessage) ;
begin
   Caption := 'PopMenu entered';
end;

procedure TForm1.CM_ExitMenuLoop(var msg: TMessage) ;
begin
   Caption := 'PopMenu exited';
end;

procedure TForm1.CM_MenuClosed(var msg: TMessage) ;
begin
   Caption := 'PopMenu closed';
end;

Delphi tips navigator:
» How to Move ListBox Items with the Mouse (Drag and Drop)
« How to Remove the "Today" Mark from the TDateTimePicker Delphi component

More Delphi Programming Quick Tips

Explore Delphi Programming

More from About.com

  1. Home
  2. Computing & Technology
  3. Delphi Programming
  4. Coding Delphi Applications
  5. Delphi Tips and Tricks
  6. Delphi 2006 Tips
  7. How to Detect a TPopupMenu's OnClose (OnPopDown) Event in Delphi applications

©2008 About.com, a part of The New York Times Company.

All rights reserved.