The following example demonstrates how to write a plug-in, clicking on which pops up a context menus with menu items as show in the figure
Follow the steps mentioned in the post to write a simple plugin 'Demo'. Create a new file 'MyMenuItem.cs' with the following content.
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
namespace MyAddin1
{
internal class MyMenuItem : MenuItem
{
    public MyMenuItem(String name)
        : this(name, name, null, 0)
    {
    }
    public MyMenuItem(String name, String text, EventHandler eh, int id)
        : base(text, eh)
    {
        m_name = name;
        m_id = id;
    }
    public String MenuName
    {
        get { return m_name; }
        set { m_name = value; }
    }
    public int MyMenuID
    {
        get{ return m_id; }
    }
    private String m_name;
    private int m_id;
}
}
Add another file 'MyMenu.cs'
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
namespace MyAddin1
{
internal class MyMenu : ContextMenu
{
    public MyMenu()
    {
        m_stackMenu = new Stack();
        m_stackMenu.Push(MenuItems);
    }
    public Menu.MenuItemCollection CurrentMenu
    {
        get { return (Menu.MenuItemCollection)m_stackMenu.Peek(); }
    }
    public void Add(String name, String text, int id)
    {
        CurrentMenu.Add(new MyMenuItem(name, text, m_eh, id));
    }
    public void PopAll()
    {
        m_stackMenu.Clear();
        m_stackMenu.Push(MenuItems);
    }
    public void PopMenu()
    {
        m_stackMenu.Pop();
    }
    public MyMenuItem PushMenu(String name, EventHandler eh)
    {
        m_menuitem = new MyMenuItem(name, name, eh, 0);
        CurrentMenu.Add(m_menuitem);
        m_stackMenu.Push(m_menuitem.MenuItems);
        return m_menuitem;
    }
    public EventHandler EventHandler
    {
        get { return m_eh; }
        set { m_eh = value; }
    }
    private Stack m_stackMenu;
    private EventHandler m_eh;
    private MyMenuItem m_menuitem;
}
}
Modify the OnConnection method in the file Connect.cs to make the add-in visible in the 'MenuBar' at the position 1
public void OnConnection(object application, ext_ConnectMode connectMode,
       object addInInst, ref Array custom)
{
   _applicationObject = (DTE2)application;
   _addInInstance = (AddIn)addInInst;
   if(connectMode == ext_ConnectMode.ext_cm_UISetup)
   {
       object[] contextGUIDS = new object[] { };
       Commands2 commands = (Commands2)_applicationObject.Commands;
       CommandBar bar = ((CommandBars)_applicationObject.CommandBars)["MenuBar"];
       try
       {
           Command command = commands.AddNamedCommand2(
                   _addInInstance, "MyAddin1", "Demo", "Do Something", true, 59,
                   ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported +
                   (int)vsCommandStatus.vsCommandStatusEnabled,
                   (int)vsCommandStyle.vsCommandStylePictAndText,
                   vsCommandControlType.vsCommandControlTypeButton);
           //Add a control for the command to the tools menu:
           if(command != null)
           {
               command.AddControl(bar, 1);
           }
       }
       catch(System.ArgumentException){
       }
   }
}
Modify Exec() method which executes whenever the command is invoked
public void Exec(string commandName, vsCommandExecOption executeOption,
       ref object varIn, ref object varOut, ref bool handled)
{
   handled = false;
   if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault)
   {
       if(commandName == "MyAddin1.Connect.MyAddin1")
       {
           ShowMenu();
           handled = true;
           return;
       }
   }
}
The ShowMenu() lists the down how the context menu structure should look like
private void ShowMenu()
{
   Point pt;
   try
   {
       CommandBar bar = ((CommandBars)_applicationObject.CommandBars)["Demo"];
       CommandBarControl control = bar.Controls[1];
       pt = new Point(control.Left, control.Top);
   }
   catch(Exception){
       pt = Control.MousePosition;
   }
   Control window = new Control();
   window.CreateControl();
   MyMenu menu = new MyMenu();
   // Register event handler with MyMenu
   menu.EventHandler = new EventHandler(this.OnClick);
   menu.PushMenu("GroupOne", menu.EventHandler);
   menu.PushMenu("GroupOneMenu", menu.EventHandler);
   menu.PopMenu();
   menu.PopMenu();
   menu.PushMenu("GroupTwo", menu.EventHandler);
   menu.PushMenu("GroupTwoMenu", menu.EventHandler);
   menu.PopMenu();
   menu.PopMenu();
   menu.PushMenu("GroupThree", menu.EventHandler);
   menu.PushMenu("GroupThreeMenu1", menu.EventHandler);
   menu.PushMenu("GroupThreeMenu2", menu.EventHandler);
   menu.PushMenu("GroupThreeMenu3", menu.EventHandler);
   menu.PopAll(); // either call PopMenu() 4 times or PopAll()
   menu.Add("MenuItem1", "MenuItem1", -1);
   menu.Add("MenuItem2", "MenuItem2", -2);
   menu.Add("AboutDemo", "AboutMenu", -3);
   menu.Show(window, pt); //displays context menu
}
Handling Click events on MenuItems
private void OnClick(Object sender, EventArgs e)
{
   try
   {
       MyMenuItem mi = (MyMenuItem)sender;
       MessageBox.Show("Hello from " + mi.MenuName);
   }
   catch(Exception ex){
       MessageBox.Show(ex.Message, ex.Source);
   }
}
Now select the Menu Item from the GroupThree
You see a message box with the message 'Hello from GroupThreeMenu3'
Your plugin is working as expected. Cheers !! :)
| Search This BlogApr 5, 2009Visual Studio - Writing a Add-In (plugin) with context menus
Subscribe to:
Post Comments
                                    (
                                    Atom
                                    )
                                  
 | 
 
 
No comments :
Post a Comment