Mega Code Archive

 
Categories / Delphi / Ide Indy
 

How to Detect a TPopupMenus OnClose (OnPopDown) Event in Delphi applications

Title: How to Detect a TPopupMenu's OnClose (OnPopDown) Event in Delphi applications 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: Drop a TPopupMenu on a Delphi form Add several menu items to the PopupMenu Include the "PopupListEx" in the uses clause 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;