Display Contextual Menu programmatically

I am updating an old RealBasic application to Xojo, but I am being stymied because the way that contextual menus are handled has changed. In the old application, for various reasons, I had a contextual menu pop up when the user simply clicked on a certain object. (I realize that this is a non-standard user interface, but this method works well and quite intuitively in this specific context.) However, Xojo won’t compile my old program. So I’d like to be able to force a RectControl to programmatically display a contextual menu. I see that for web controls there is a PresentContextualMenu method, but that doesn’t seem to exist for desktop apps. I could call the RectControl.ConstructContextualMenu event myself, but I don’t know how to construct the Base item. Any ideas about how I might proceed?

Added the following code in the “Action” event handler of a button and the menu is displayed (Windows 7, Xojo 2014r2.1) when the button is clicked. This code was copied from RB or some other forum. No longer have reference to the origin.

Not sure if this is whats required here.

// ===============================
// Define menu extries
// ===============================
dim base as new MenuItem
base.Append( new MenuItem( “Copy” ) ) '0
base.Append( new MenuItem( “Paste” ) ) '1
base.Append( new MenuItem( “Select All” ) ) '2
base.Append( new MenuItem( “Clear” ) ) '3
base.Append( new MenuItem( MenuItem.TextSeparator ) ) '4
base.Append( new MenuItem( “Find” ) ) '5
base.Append( new MenuItem( “Find Next” ) ) '6
// ===============================
// Set the enabled status
// ===============================

// ===============================
// Carry out actions
// ===============================
dim hitItem as MenuItem
hitItem = base.PopUp
MsgBox( “Hello”)[/code]

The same code also displays the menu when placed in the “Open” event handler of the same button.


There are essentially three ways to go:

  1. Use the ConstructContextualMenu / ContextualMenuAction event handlers to build the menu and respond to selections, but this (as the name implies) only works for “ontextualy generated” (right click, etc.) menus. This is likely the most compatible solution since it handles all the ways that contextual menus can be evoked, but might not be what you want.

  2. Create a menu programmatically when the user clicks the object. This is a bit more difficult since you have to use the “AddHandler” method to handle the menu events, but this is probably the most OO way to go.

  3. Create a menu bar menu that is set to not visible. Then use the mnuMyMenu.Popup method to get it to popup wherever you want.

Hope this helps.

Thank you both very much for your suggestions. I’ll try the menu.Popup approach and see if that works.

Thanks, Syed, your method worked perfectly, and was exactly what I needed. I also appreciate your message, William because it helped me see the range of possibilities. I appreciate the help very much!

I struggled with this for a while today… Got lots of MenuHasParentException errors
I found #3 by William K works perfectly for me.

menuitem.clone is for exactly this purpose

basically it USED to be possible to have the same instance of a menu item in multiple menus at one time but that is no longer supported

Thanks Norman. That’s what I’m using.

Basically I made a MenuBar (at the app level… I think I can put it in my Window control, since that’s where I’ll use it), and I set it’s menu items to not visible, and then I used the ConstructContextualMenu event to check to see if I had selected list items, and if so, clone them, set them to visible and add them to the ListBox.

BTW I really enjoy how active the XoJo forums are. It’s really amazing.

oh !!!
I’d just create the things manually using New Menuitem and set the appropriate properties but thats me :slight_smile:

lol, ok - so I did hugely over complicate it.

My problem began when I needed to only show the context menu if I had a selected row in the list box. I removed all the code I showed originally. I realized that the statement:

If Self.SelectedMaterialsRow > 0 Then .. End If

already handled that condition, so I just did this:

If Self.SelectedMaterialsRow > 0 Then ' this value is > 0 when there is a selected list item.
  Dim addSupply As New MenuItem
  addSupply.Name = "AddSupplyMenuItem"
  addSupply.Text = "Add Supply Item"
  addSupply.Tag = "addSupply"
  Dim removeSupply As New MenuItem
  removeSupply.Text = "Remove Supply Item"
  removeSupply.Name = "RemoveSupplyMenuItem"
  removeSupply.Tag = "removeSupply"
  base.Append ( addSupply )
  base.Append ( removeSupply )
  Return True 
End If 

and handled it with the ContextualMenuAction event with a Select Case on HitItem.Tag… problem solved.

Thanks for your help!