Popup Menus

BlitzMax Forums/Brucey's Modules/Popup Menus

Glenn Dodd(Posted 2008) [#1]
Looking at the Menu sample program i can see where the popup menu is displayed.

Function OnRightUp(event:wxEvent)
Local x:Int, y:Int
wxMouseEvent(event).GetPosition(x, y)
MyFrame(event.parent).ShowContextMenu(x, y)
End Function

what i would like to do is recognise the control under the mouse. They will be listctrl's but the right click might occur in a section that doesn't have an item to respond to OnListItemRightClick. If i click on the header then i can respond with OnListColumnRightClick.

or should i be using wxWindow.wxMouseEvent.OnRightUp on the specific controls?

Cheers
Glenn


Glenn Dodd(Posted 2008) [#2]
well just tried wxWindow.wxMouseEvent.OnRightUp and that wasn't what i was after :)


Brucey(Posted 2008) [#3]
There's a HitTest() method that's part of wxListCtrl which can give you information as to what is under a specific point on the control - like an item, or a header, etc.

Haven't used it myself yet tho.


Glenn Dodd(Posted 2008) [#4]
ah yes, i remember reading about that a while ago.
I don't see it in wxCodeGen though in the events, so i forgot about it...

Will try tomorrow.

Cheers


Brucey(Posted 2008) [#5]
It's not an event.

You would catch a mouse event (say right-click), and then call HitTest() passing in the coords, and getting back the flags param, as well as the item number for that coord.

probably :-)


DavidDC(Posted 2008) [#6]
I'm not sure the flags param works? Last I tried to use it, it always returned 0.

The event I'd connect to is wxEVT_RIGHT_DOWN. HitTest() will return the item (as in list row) under mouse of the gadget you received the event from. But I'm not sure it is necessary?

Just connect up the right click mouse event to every gadget you want to check. If you don't want the gadget itself to respond to the event then remove event.Skip()

[edited to correct an error re HitTest()]


Glenn Dodd(Posted 2008) [#7]
Sample code:
Trying to establish which Listbox had the right click.

Main:


Gui:


The debug shows the first listbox as -203 (getid) and the second as -204. The third listbox is not responding to the right click (Intentional)

Stepping through the debug variables i can't identify these numbers.
Also object "a" doesn't mean much to me...

So each listbox is being identified uniquely but i don't know what the code means.

Cheers
Glenn


Glenn Dodd(Posted 2008) [#8]
I haven't tried HitTest() yet because i am expecting the right click to occur on empty listboxes...


Brucey(Posted 2008) [#9]
I haven't tried HitTest() yet

In which case HitTest() probably returns -1 for nothing?

The debug shows the first listbox as -203 (getid) and the second as -204.

For every control you make, you can assign a unique Id. You can use this in the event system to refer to a specific control by its id. This is especially useful when a number of events use the same callback function. (otherwise, you might not care about assigning a unique id to a control that uses its own callback function).

If you don't assign an id to a control, one is assigned for you, for internal use, but your application can just assume that value is wxID_ANY.

In wxFormBuilder, you can set your Id in the properties for the control, by giving it a name, which will be made into a Const variable by wxCodeGen.

For example, you make the id something like ID_BORIS, and you'll have that generated as a Const with a unique int value.
You could then, in a shared callback method have something like :
Select event.GetId()

    Case ID_BORIS
        Debuglog "You clicked on Boris!"

    Case ID_FRED
        Debuglog "You clicked on Fred!"

End Select



Glenn Dodd(Posted 2008) [#10]
Cool.
That does the trick for me.
Many Thanks again


Glenn Dodd(Posted 2008) [#11]
Working Example:

TestPopupsMain.bmx


TestPopups.bmx


Thanks to Brucey and David for the help.


Brucey(Posted 2008) [#12]
Glad you got it sorted!

Could you send me the fbp please?
I'm wondering why it's generating this :
Connect(ID_lb1, wxEVT_RIGHT_UP, _RightClickForPopup)
Connect(ID_lb2, wxEVT_RIGHT_UP, _RightClickForPopup)
		
m_listBoxPopup1.ConnectAny(wxEVT_RIGHT_UP, _RightClickForPopup, Null, Self)
m_listBoxPopup2.ConnectAny(wxEVT_RIGHT_UP, _RightClickForPopup, Null, Self)


Thanks :-)


Glenn Dodd(Posted 2008) [#13]
Sent.
What is wrong with it?


Brucey(Posted 2008) [#14]
Nothing, it appears :-)

Thanks for clearing things up. I wondered why the code was generating essentially duplicate Connects, but it doesn't with mine.

Nothing to see here, move along, move along!

:o)


Glenn Dodd(Posted 2008) [#15]
sorry to resurrect this older thread.

TestPopupsGUI.bmx


and TestPopups.bmx


The current version of wxCodeGen seems to generate the 2 connect lines which i have commented out.
' Connect(ID_lb1, wxEVT_RIGHT_UP, _RightClickForPopup)
' Connect(ID_lb2, wxEVT_RIGHT_UP, _RightClickForPopup)

but these two are the ones that work in this example for the listboxes.

m_listBoxPopup1.ConnectAny(wxEVT_RIGHT_UP, _RightClickForPopup, Null, Self)
m_listBoxPopup2.ConnectAny(wxEVT_RIGHT_UP, _RightClickForPopup, Null, Self)

also the Function _RightClickForPopup(event:wxEvent) has MyFrame2Base(event.sink) whereas the current wxCodeGen gives me MyFrame2Base(event.parent) whcih my listbox is not responding to.

am i doing something wrong?

Cheers
Glenn


Glenn Dodd(Posted 2008) [#16]
Hi Bruce,
Just checking what wxCodeGen should be doing.
Connect(ID_lb1, wxEVT_RIGHT_UP, _RightClickForPopup)
or
m_listBoxPopup1.ConnectAny(wxEVT_RIGHT_UP, _RightClickForPopup, Null, Self)

Currently it does the first but that doesn't appear to trigger the event for me in the sample above

Cheers
Glenn


Glenn Dodd(Posted 2008) [#17]
I have this working
	Function OnContextMenu(event:wxEvent)
		Local frame:MyFrame = MyFrame(event.parent)
		Local x:Int, y:Int
		
		wxContextMenuEvent(event).GetPosition(x, y)
		' This line makes sure the popup menu is positioned where the mouse is.
		frame.ScreenToClient(x, y)
		' This line displays the popup menu
		frame.ShowContextMenu(x, y)
	End Function
	
	Method ShowContextMenu(x:Int, y:Int)
		Local menu:wxMenu = New wxMenu.Create()
		
		menu.Append(Menu_Add_SelectorType, "Add a NEW Selector Type")
		menu.Append(Menu_Edit_SelectorType, "Edit the highlighted Selector Type")
		menu.AppendSeparator()
		menu.Append(Menu_Delete_SelectorType, "Delete the highlighted Selector Type")
		
		PopupMenu(menu, x, y)
		
		menu.Free()
	End Method


I can display the menu.
I can click the menu.

I need to do something on each item.
I think something like this:
	Method ClickedpopupItem(event:wxMenuItem)
		DebugLog "Popup Menu item Chosen"
		Select event.GetId()

		    Case Menu_Add_SelectorType
        	DebugLog "You clicked on ADD"

		End Select		
	End Method


The Select/Case/End Select will give me an individual action.
What do i need to do to link this method with the items from the menu?

Cheers
Glenn


Glenn Dodd(Posted 2008) [#18]
got it.
' intercept all menu events And Log them in this custom event handler
PushEventHandler(New MyEvtHandler.Create(Self))


is needed in the Frame OnInit method and
' A small helper type which intercepts all menu events And logs them
Type MyEvtHandler Extends wxEvtHandler

	Field frame:MyFrame
	
	Method Create:MyEvtHandler(_frame:MyFrame)
		frame = _frame
		Return MyEvtHandler(CreateHandler())
	End Method
	
	Method OnInit()
	    Connect(wxID_ANY, wxEVT_COMMAND_MENU_SELECTED, OnMenuEvent)
	End Method
		
	Function OnMenuEvent(event:wxEvent)
		DebugLog "Popup Menu item Chosen"
		Select event.GetId()

		    Case Menu_Add_SelectorType
        	DebugLog "You clicked on ADD"

'    		Case ID_lb2
 '       	DebugLog "You clicked on Fred!"

		End Select	
'		MyEvtHandler(event.parent).frame.LogMenuEvent(event)
	
		event.Skip()
	End Function

End Type

is needed to do the actual work.


Brucey(Posted 2008) [#19]
I've made mouse events be raised against the actual control, rather than via Connect() on the parent, which doesn't always work.
(In rev 382).


Glenn Dodd(Posted 2008) [#20]
Many thanks
I will resync right away.

Cheers
Glenn