More fun with contextual menus

Thanks to Joe, I got my answer to intercepting Paste from a contextual menu here. So I constructed my own menu, cloning items from the Edit menu, and it’s good. I can now intercept Paste (or Cut, Copy, etc.) whether it’s selected from the main menu or the contextual menu, and I don’t even have to put any additional handlers in place as the menu handlers of the individual controls will do the job. Cool.


The problem now is that the items aren’t properly enabled/disabled with this scheme. For example, Copy is always enabled whether there is text highlighted or not. Cut is not enabled initially, but will be after you select some text. Except then, it won’t disable until the field is empty again, whether you unhighlight or not.

And I can’t override this behavior myself even if I manually call “EnableMenuItems” first.

Before I give up on cloning the original menu items and construct the menu anew (requiring additional handler code in the controls), is there a way to get the contextual menu items to respect the enabled/disabled state of their menubar counterparts?

Do you handle enabling/disabling the menu items yourself?

In EnableMenuItems, yes, at least the ones I override or add. Cut and Copy are not among those.

If I try to change the Enabled state of my MenuItem clones directly in the ConstructContextualMenu event, it’s just ignored.

Even if you set AutoEnable to False?

Yup, that was the key. After I clone the menu, I have to set AutoEnable to false, Enabled to true, and clear the keys for good measure.

I created a Shared convenience method in my subclass that does this for me:

 Shared Sub AppendMenuCloneIf(base As MenuItem, menuToClone As MenuItem, condition As Boolean = true)
  // If the condition is true, will append the menu to the base.
  // Will also clear the keys, set auto-enable to false, and enable the menu
  if not condition then return
  dim c as MenuItem = menuToClone.Clone
  dim stack() as MenuItem
  stack.Append c
  while stack.Ubound <> -1
    dim thisMenu as MenuItem = stack.Pop
    thisMenu.KeyboardShortcut = ""
    thisMenu.AutoEnable = false
    thisMenu.Enabled = true
    if thisMenu.Count <> 0 then
      dim lastIndex as integer = thisMenu.Count - 1
      for i as integer = 0 to lastIndex
        stack.Append thisMenu.Item( i )
      next i
    end if
  base.Append c
End Sub

Thanks Greg.