Detecting when a popupmenu disappears when mouse clicked out
-
- User
- Posts: 55
- Joined: Mon Jul 18, 2016 6:43 pm
Detecting when a popupmenu disappears when mouse clicked out
Running PureBasic 5.42 LTS (Linux - x64). When an item in a popupmenu is clicked, a #PB_Event_Menu is sent and I can then process the selection and free the menu in the handler. But suppose I click outside the menu and it disappears with no selection made. How can I detect this situation and take action to cleanup? I don't see such an event, or a way to query if the menu is hidden.
Re: Detecting when a popupmenu disappears when mouse clicked
You should be able to put the cleanup code directly after DisplayPopupMenu(), I think.
-
- User
- Posts: 55
- Joined: Mon Jul 18, 2016 6:43 pm
Re: Detecting when a popupmenu disappears when mouse clicked
if I do this:
Debug("Before DisplayPopupMenu")
DisplayPopupMenu(NetworkMenu,WindowID(Window_0))
Debug("After DisplayPopupMenu")
both debug messages go out with the menu still visible. So DisplayPopupMenu returns immediately after displaying the menu, not after it is released.
I am hoping to create a reasonable emulation of the win32api TrackPopupMenu. I can get close except for the case when no selection is made and the menu is hidden by clicking outside. The fact that the menu knows to disappear means someone somewhere is getting an event.
Debug("Before DisplayPopupMenu")
DisplayPopupMenu(NetworkMenu,WindowID(Window_0))
Debug("After DisplayPopupMenu")
both debug messages go out with the menu still visible. So DisplayPopupMenu returns immediately after displaying the menu, not after it is released.
I am hoping to create a reasonable emulation of the win32api TrackPopupMenu. I can get close except for the case when no selection is made and the menu is hidden by clicking outside. The fact that the menu knows to disappear means someone somewhere is getting an event.
Re: Detecting when a popupmenu disappears when mouse clicked
I only know how to do it on Windows, but that doesn't help if you're on Linux.dougmo52usr wrote:Running PureBasic 5.42 LTS (Linux - x64)
Does Linux have a way to know the foreground window, like Windows can? If so, try storing the foreground window handle before opening the menu, and then when a new window becomes foreground which isn't due to a menu event, then your app will know something other than the menu has been clicked (meaning the menu will be closed).
For those interested, here is the Windows method:
Code: Select all
Global menuopen
Procedure Callback(hWnd,Message,wParam,lParam)
result=#PB_ProcessPureBasicEvents
If Message=#WM_INITMENUPOPUP
If menuopen=0
menuopen=wParam
Debug "opened"
EndIf
ElseIf Message=#WM_UNINITMENUPOPUP
If wParam=menuopen
menuopen=0
Debug "closed"
EndIf
EndIf
ProcedureReturn result
EndProcedure
OpenWindow(0,200,200,200,100,"test",#PB_Window_SystemMenu)
ButtonGadget(0,10,10,180,80,"Click to open menu")
CreatePopupMenu(0)
MenuItem(0,"test")
SetWindowCallback(@Callback())
Repeat
ev=WaitWindowEvent()
If ev=#PB_Event_Gadget
DisplayPopupMenu(0,WindowID(0))
EndIf
Until ev=#PB_Event_CloseWindow
-
- User
- Posts: 55
- Joined: Mon Jul 18, 2016 6:43 pm
Re: Detecting when a popupmenu disappears when mouse clicked
This seems to emulate some of TrackPopupMenu. That is it displays a popupmenu, waits for the popupmenu to disappear, and returns the id of the clicked item. I prefer to start numbering items at 1 with 0 being menu closed with no selection.
Code: Select all
EnableExplicit
Global MainWind
Global MainMenu
Global PopuMenu
Global Selected
Global ItemText
Enumeration MainMenuIDs
#EMenuIdPopup1=1
#EMenuIdPopup2
EndEnumeration
Declare TrackPopupMenu(hMenu)
Declare AppMainWindow()
AppMainWindow()
Procedure AppMainWindow()
MainWind = OpenWindow(#PB_Any, #PB_Ignore, #PB_Ignore, 250, 200, "TrackPopupMenu example", #PB_Window_SystemMenu | #PB_Window_TitleBar)
If IsWindow(MainWind)
ItemText = StringGadget(#PB_Any, 25, 100, 200, 25, #Null$)
Selected = StringGadget(#PB_Any, 25, 130, 200, 25, #Null$)
MainMenu = CreateMenu(#PB_Any,WindowID(MainWind))
If IsMenu(MainMenu)
MenuTitle("Main Menu")
MenuItem(#EMenuIdPopup1,"Popup1")
MenuItem(#EMenuIdPopup2,"Popup2")
Protected Event
Repeat
Event = WaitWindowEvent()
If MainWind = EventWindow()
Select Event
Case #PB_Event_Menu
PopuMenu = CreatePopupMenu(#PB_Any)
If IsMenu(PopuMenu)
Protected ItemId
For ItemId=1 To 5
MenuItem(ItemId,"Popup " + Str(EventMenu()) + " Item " + Str(ItemId))
Next
SetGadgetText(Selected,#Null$)
Protected ItemSelected = TrackPopupMenu(PopuMenu)
SetGadgetText(Selected,"TrackPopupMenu returned " + Str(ItemSelected))
If ItemSelected
SetGadgetText(ItemText,"Clicked " + GetMenuItemText(PopuMenu,ItemSelected))
Else
SetGadgetText(ItemText,"Clicked outside menu")
EndIf
FreeMenu(PopuMenu)
EndIf
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow ; Quit on any window close
EndIf
EndIf
EndProcedure
;TrackPopupMenu creates a borderless window and attaches the menu to it.
;The operation is basically in it's message loop as follows:
; #PB_Event_ActivateWindow - fired by OpenWindow, DisplayPopupMenu is called
; #PB_Event_DeactivateWindow - fired by DisplayPopupMenu getting the focus
; #PB_Event_ActivateWindow - fired by popupmenu disappearance
; #PB_Event_Menu - fired by menu item selection
Procedure TrackPopupMenu(hMenu)
;0 if no menuitem selected
Protected MenuItemID = 0
; fires first #PB_Event_ActivateWindow
Protected thisWindow = OpenWindow(#PB_Any, DesktopMouseX(),DesktopMouseY(), 1, 1, #Null$, #PB_Window_BorderLess)
;If window successfully created
If IsWindow(thisWindow)
Protected MenuDisplayed = #False
Protected Event
Repeat
;if window event comes in
Event = WaitWindowEvent()
;and it is directed at this window
If thisWindow = EventWindow()
;process event
Select Event
;if menu item clicked, handle it
Case #PB_Event_Menu
MenuItemID = EventMenu()
;get this event when:
; 1. OpenWindow is called
; 2. Popup menu disappears
;menu will disappear triggering a #PB_Event_ActivateWindow
Case #PB_Event_ActivateWindow
;if menu is not yet displayed, event came from OpenWindow
If Not MenuDisplayed
; display the popupmenu which fires a #PB_Event_DeactivateWindow
DisplayPopupMenu(hMenu,WindowID(thisWindow),DesktopMouseX(),DesktopMouseY())
;otherwise it came from PopupMenu disappearance
Else
;so tell the window to close
PostEvent(#PB_Event_CloseWindow,thisWindow,0)
EndIf
;fired when menu is shown covering the window
Case #PB_Event_DeactivateWindow
;MenuDisplayed state
MenuDisplayed = #True
EndSelect
EndIf
Until Event = #PB_Event_CloseWindow
EndIf
ProcedureReturn MenuItemID
EndProcedure