网站主页   操作系统    网络工程    服务器    网页制作    数据库    程序开发    网络安全    办公软件   
讲座日期: 本周六下午1点30分 抢座
讲座地点: 北大青鸟马甸校区
主讲老师: 王老师 金牌讲师
讲座主题: 网络安全
讲座内容: 检测、防御、黑客信息,如何过滤不安全的网站,如何防御黑客的进攻。
订座电话: 010-82011432/33
  您当前位置:主页 > 网络学院 > 程序开发 > C#教程 >

VS.NET 2003集成环境插件开发指南(一)----操纵菜单




             简介――插件能做什么?

插件能做很多事情,例如:

1、   编写如一样的开发环境代码辅助工具

2、   编写如这样的代码模板工具

3、   编写代码生成器,根据自定义的一些条件自动生成代码。如现在比较流行的一些代码生成工具,如果和开发环境集成,使用起来应该会更加方便。

4、   编写如这样的调试工具,可以在调试时查看的内容。

5、   甚至还可以在里集成搜索引擎,或将集成到。

这里不再一一列举,总而言之,凡是可以和开发环境相关的,都能以插件的形式进行。

开发插件,目前有两种形式:一是利用向导生成的外接程序;二是利用微软的开发包(:微软合作伙伴计划)。本文讨论的是第一种方法。

             程序框架概述

在中选择新建项目à其他项目à扩展性项目à外接程序,按照向导生成代码,最后会生成两个工程文件,一个是外接程序项目,一个是外接程序安装项目。可以在外接程序项目里看到生成的项目文件中有个文件,该文件有以下几个部分:

1、   类的继承接口及其常量定义

     [GuidAttribute("952A6CFF-8516-4DA0-B0BA-519CB9614525"), ProgId("STDTools.Connect")]

public class Connect : Object, Extensibility.IDTExtensibility2, IDTCommandTarget

{}

类主要从两个接口继承,一个是Extensibility.IDTExtensibility2接口,该接口主要定义了下面几个方法:

OnAddInsUpdate 方法:在环境中加载或卸载外接程序时发生。

OnBeginShutdown 方法:正在关闭环境时发生。

OnConnection 方法:将外接程序加载到环境中时发生。

OnDisconnection 方法:当从环境中卸载外接程序时发生。

OnStartupComplete 方法:环境启动完毕时发生。

接口则定义了以下两个方法

Exec 方法:在VS开发环境中选择了某个外接菜单命令时被VS环境所调用。

QueryStatus方法:当VS环境要显示外接菜单时调用该方法查询菜单的状态。

该方法返回指定的已命名命令的当前状态,无论此命令是启用、禁用还是隐藏

 

2、   OnConnection()函数:

本事件处理函数是在插件被加载时发生,一般用于做一些初始化工作,如创建菜单等。该函数的传入参数如下:

object application:定义了IDE自动化对象

 Extensibility.ext_ConnectMode connectMode:连接模式,指明了插件当前的连接模式

ext_cm_AfterStartup 外接程序是在应用程序启动后加载的,或是通过将相应 AddIn 对象的 Connect 属性设置为 True 加载的。

ext_cm_Startup 外接程序是在启动时加载的。

ext_cm_UISetup 外接程序自安装后首次被启动。

object addInInst:表示外接程序实例的 AddIn 对象。

ref System.Array custom: 一个 Variant 数组,可以用来提供附加数据,一般不太常用。

 

3、   OnDisconnection()函数:系统卸载插件时被调用

本事件处理函数是在插件被卸载时发生,其传入参数如下

Extensibility.ext_DisconnectMode disconnectMode:

ext_dm_HostShutdown:外接程序是在开发环境关闭时卸载的。

ext_dm_UserClosed:外接程序是在用户清除“外接程序管理器”对话框中该外接程序的复选框时卸载的

ext_dm_UISetupComplete:外接程序是在环境安装完成后和在 OnConnection 方法返回后卸载的。

ref System.Array custom:

4、   QueryStatus()函数:系统查询菜单状态

 

该方法有四个传入参数

CmdName 要检查的命令的名称。

NeededText

一个 常数,指定是否返回检查信息,如果返回,还指定返回信息的类型。

vsCommandStatusTextWantedNone不返回信息。

vsCommandStatusTextWantedName返回命令名。

vsCommandStatusTextWantedStatus返回命令状态。

StatusOption

一个指定命令的当前状态的 常数。

vsCommandStatusUnsupported 命令在此上下文中不受支持。

vsCommandStatusSupported 命令在此上下文中受支持。

vsCommandStatusEnabled 命令当前处于启用状态。

vsCommandStatusLatched 命令当前处于锁存状态。

vsCommandStatusNinched 留作将来使用。

vsCommandStatusInvisible 命令当前处于隐藏状态。

CommandText

指定 vsCommandStatusTextWantedStatus 时返回的文本。

5、   Exec()函数:

在开发环境中选择了某个外接菜单命令时被环境所调用,在这里可以编写自己的响应代码,例如运行自己的程序或弹出某个窗口。

             处理菜单

在方法中可以进行一系列初始化工作,其中之一就是生成菜单

1、   添加菜单条菜单和工具条菜单

applicationObject = (_DTE)application;

addInInstance = (AddIn)addInInst;

if(connectMode == Extensibility.ext_ConnectMode.ext_cm_UISetup

|| connectMode == Extensibility.ext_ConnectMode.ext_cm_Startup)

{//    如果是安装状态或是插件刚被启动的状态,则创建菜单

object []contextGUIDS = new object[] { };

 

//获取IDE环境的Command集合和CommandBar集合

Commands commands = applicationObject.Commands;

_CommandBars commandBars = applicationObject.CommandBars;

 

try

{

    //菜单条对象和工具条对象都是CommandBar类型

CommandBar menuObj,toolbarObj;

 

//生成新的子菜单对象,将会被插入到菜单条和工具条对象上

Command commandObj = commands.AddNamedCommand(addInInstance,

 "PublishUserManage",

 "添加用户管理代码",

"添加用户管理的代码",

true,

127,

ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported+(int)vsCommandStatus.vsCommandStatusEnabled

);

//如何确定在按钮上显示的位图的ID,可以利用附录中的工具

 

#region 相关帮助信息

/*

  返回一个 Command 对象

         [C#]

         public Command AddNamedCommand(

         AddIn pAddIn, //用于添加新命令的 AddIn 对象

string Name, //新命令的名称缩写。AddNamedCommand 会自动给此缩写加上前面类前缀的

             //ProgId("STDTools.Connect")中的"STDTools.Connect"以创建唯一的名称

         string ButtonText,//在命令绑定到以名称而不是以图标显示的按钮时使用的名称

          string Tooltip,    //当用户将鼠标指针悬停在任何绑定到新命令的控件上时所显示的文本

bool MSOButton,    //指示指定命令的按钮图片是否是 Office 图片。True = 按钮图片从

//Office资源文件中获取。False则表示按钮的图片资源来源于其他的文件

         int Bitmap,        //在按钮上显示的位图的 ID

object[] ppsaContextUIGUIDs,

//GUID的SafeArray,它确定启用此命令的环境上下文(即调试模式、设计模式等

int DisableFlags  

//确定当您提供了 ContextUIGUIDs 而当前它们都不活动时,此命令的禁用状态是不可见还是灰色的

         );

 

              DisabeFlags命令的当前状态。

              vsCommandStatusUnsupported 0 命令在此上下文中不受支持。

              vsCommandStatusSupported 1 命令在此上下文中受支持。

              vsCommandStatusEnabled 2 命令当前处于启用状态。

              vsCommandStatusLatched 4 命令当前处于锁存状态。

              vsCommandStatusNinched 8 留作将来使用。

              vsCommandStatusInvisible 16 命令当前处于隐藏状态。

 

这里有几点要说明:

     1、菜单图片:

bool MSOButton参数为true,意味着该菜单命令的图片是来源于Office资源库,则后面的int Bitmap(位图ID号)则指明了是哪个图片。如何知道哪个ID号对应哪个图片?可以从微软的页面上下载一个用VBA写的工具,该工具列举出了所有的图片资源(附录工具中已经包含FaceID.xls)。

如果不想用Microsoft Office自带的图片资源,则需要先在自己的解决方案中添加一个MFC DLL的工程,然后在其中加入图片资源;然后将MSOButton设为False,将Bitmap位图ID设为该资源文件中图片资源的ID号,然后还要在安装程序里添加一个文件夹,同时添加注册表项。具体过程就不再多说了,可以看参考资料

2、菜单项的名称

函数的第二项参数string Name(本例中是PublishUserManage),系统在生成菜单对象时会自动在Name前面添加本插件的ProgID代表的字符串作为菜单对象的全名。后面在根据名称检索该菜单对象时,需要用全名,本例中应该是STDTools.Connect.PublishUserManage;

*/

#endregion

 

 

 

//添加主菜单

CommandBarButton buttonObj;

 

//创建主菜单项和工具条

menuObj = (CommandBar) applicationObject.Commands.AddCommandBar("代码生成(&C)" ,

  vsCommandBarType.vsCommandBarTypeMenu,

  applicationObject.CommandBars["MenuBar"],10);

 

#region 相关帮助信息

 

/*

  public object AddCommandBar(

       string Name,//新命令栏的名称

       vsCommandBarType Type,//用于确定命令栏类型的 vsCommandBarType 常数

       CommandBar CommandBarParent,//要添加新命令栏的 Office CommandBar 对象

       int Position// 命令栏中放置新命令栏的索引位置,从 1 开始

  );

 

vsCommandBarType的取值为:

       vsCommandBarTypePopup 10 弹出命令栏

       vsCommandBarTypeToolbar 23 工具栏命令栏

       vsCommandBarTypeMenu 24 菜单命令栏

 

 

*/

 

#endregion 相关帮助信息

 

toolbarObj = (CommandBar) applicationObject.Commands.AddCommandBar(

                "CodeTools(&C)",

vsCommandBarType.vsCommandBarTypeToolbar,

null,

-1);

toolbarObj.Position = Microsoft.Office.Core.MsoBarPosition.msoBarTop;

 

//增加子菜单

 

//将子菜单加入主菜单和工具条

buttonObj = (CommandBarButton) commandObj.AddControl(menuObj, menuObj.Controls.Count + 1);

buttonObj = (CommandBarButton) commandObj.AddControl(toolbarObj, toolbarObj.Controls.Count + 1);

buttonObj.Style = MsoButtonStyle.msoButtonIcon;

 

//将子菜单加入Project的右键菜单

CommandBar projBar = this.applicationObject.CommandBars["Project"];

commandObj.AddControl(projBar,1);

 

}

catch(System.Exception ex)

{

string error = ex.Message;

//                   MessageBox.Show(error);

}

 

2、   添加右键弹出快捷菜单

除了上面在开发环境中添加常规菜单外,还允许用户为开发环境添加一些右键弹出菜单项。下面代码是为代码编辑窗口添加右键弹出菜单。

            //检索代码编辑窗口右键弹出菜单的工具条

CommandBar projBar = this.applicationObject.CommandBars["Code Window"];

//将自己的菜单项加入工具条

            commandObj.AddControl(projBar,1);

如果想在鼠标右键点击“解决方案资源管理器”中的某项目结点时弹出的菜单条中添加自己的菜单项,则只需把上面的改成即可。如何知道是或这个没有什么资料说明,但是也很简单,只要编写一个插件程序,列举出所有的菜单条对象就行了。幸好笔者已经做了这件事情,把所有的菜单条对象的名称都列在附录的文件里了,你所要做的就是根据名称去猜哪个是你所需要的菜单条了。

3、   卸载菜单

为什么需要卸载菜单?

因为如果在你的插件中没有处理卸载菜单,则用户通过“工具à外接程序管理器”暂时关闭了你的插件,或者是通过添加/删除程序卸载了你的插件时,菜单项依然存在,但是却已经不能执行命令,这是不合理的。

         public void OnDisconnection(Extensibility.ext_DisconnectMode disconnectMode,

ref System.Array custom)

         {

              /*

              CmdName 要检查的命令的名称。

                   NeededText

                   一个 vsCommandStatusTextWanted 常数,指定是否返回检查信息,

如果返回,还指定返回信息的类型。

                       vsCommandStatusTextWantedNone不返回信息。

                       vsCommandStatusTextWantedName返回命令名。

                       vsCommandStatusTextWantedStatus返回命令状态。

                   StatusOption

                   一个指定命令的当前状态的 vsCommandStatus 常数。

                       vsCommandStatusUnsupported 命令在此上下文中不受支持。

                       vsCommandStatusSupported 命令在此上下文中受支持。

                       vsCommandStatusEnabled 命令当前处于启用状态。

                       vsCommandStatusLatched 命令当前处于锁存状态。

                       vsCommandStatusNinched 留作将来使用。

                       vsCommandStatusInvisible 命令当前处于隐藏状态。

                   CommandText

                   指定 vsCommandStatusTextWantedStatus 时返回的文本。

              */

              try

              {

                   if(disconnectMode == Extensibility.ext_DisconnectMode.ext_dm_HostShutdown

 || disconnectMode == Extensibility.ext_DisconnectMode.ext_dm_UserClosed )

                   {

                       Command commandObj = this.applicationObject.Commands.Item(

"STDTools.Connect.PublishUserManage",-1);

                       if(commandObj != null)

                            commandObj.Delete();

                       CommandBar menuObj = (CommandBar)

this.applicationObject.CommandBars["代码生成(&C)"];

                       CommandBar toolbarObj = (CommandBar)

this.applicationObject.CommandBars["CodeTools(&C)"];

                       if (menuObj != null)

                       {

                            this.applicationObject.Commands.RemoveCommandBar(menuObj);

                       }

                       if (toolbarObj != null)

                       {

                         this.applicationObject.Commands.RemoveCommandBar(toolbarObj);

                       }

                   }

              }

              catch (Exception ex)

              {

                   MessageBox.Show(ex.Message);

              }

}

上面的代码比较简单,先判断是不是环境正在关闭或用户通过外接程序暂停了插件,然后查找到子菜单项并删除,再查找到主菜单项和工具条项,从系统菜单集合里移除掉这些命令条对象。

4、   确定菜单状态

菜单显示时有一项比较重要的工作,就是根据应用环境的不同,菜单对象的显示状态也在不断变化。也即可用,禁用,不显示。每当集成环境要显示一个插件的菜单时,它会调用()方法查询该菜单应该显示的状态。如下代码所示:

         public void QueryStatus(string commandName,

EnvDTE.vsCommandStatusTextWanted neededText,

ref EnvDTE.vsCommandStatus status, ref object commandText)

         {

              /*

                   CmdName:要检查的命令的名称。

                   NeededText:一个 vsCommandStatusTextWanted 常数,指定是否返回检查信息,

如果返回,还指定返回信息的类型。

 

                   status:一个指定命令的当前状态的 vsCommandStatus 常数。

                       vsCommandStatusUnsupported 0 命令在此上下文中不受支持。

                       vsCommandStatusSupported 1 命令在此上下文中受支持。

                       vsCommandStatusEnabled 2 命令当前处于启用状态。

                       vsCommandStatusLatched 4 命令当前处于锁存状态。

                       vsCommandStatusNinched 8 留作将来使用。

                       vsCommandStatusInvisible 16 命令当前处于隐藏状态

 

                   CommandText:指定 vsCommandStatusTextWantedStatus 时返回的文本。

               */

              if(neededText==EnvDTE.vsCommandStatusTextWanted.vsCommandStatusTextWantedNone)

              {

                   if(commandName == "STDTools.Connect.PublishUserManage")

                   {

                       status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported;

                      

                       if(//此处省略判断状态的代码.)

                        {

                            status =

(vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|

vsCommandStatus.vsCommandStatusEnabled;

                       }

                   }

              }

}

上面的代码先预设菜单项状态为受支持状态如果不受支持,则菜单不会显示,然后判断条件满足的情况下添加菜单为可用状态,如果不满足条件,则菜单为禁用状态。

5、   执行菜单命令

当用户选择插件的菜单项时,集成环境会调用()方法,如下所示:

         public void Exec(string commandName,

EnvDTE.vsCommandExecOption executeOption,

ref object varIn, ref object varOut, ref bool handled)

         {

              /*

vsCommandExecOption 指定执行选项的常数。

常量 值 说明

vsCommandExecOptionDoDefault 0 执行默认行为,无论是否提示用户输入。

vsCommandExecOptionPromptUser 1 获取用户输入后执行命令。

vsCommandExecOptionDoPromptUser 2 不提示用户就执行命令。

例如,选择工具栏上的“打印”按钮导致立即打印文档,而不必用户输入。

vsCommandExecOptionShowHelp 3 显示可能存在的相应命令的帮助,但不执行命令。

               */

              handled = false;

              if(executeOption == EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault)

              {

                   if(commandName == "STDTools.Connect.PublishUserManage")

                   {

                       //此处略去200字^_^

                       handled = true;

                       return;

                   }

              }

}

上面代码查询被执行的菜单的名称是本插件所期望的名称,则执行一段代码,如显示窗口等,执行成功,则设置handled为true,告诉集成环境已经成功执行命令。

 

 

上一篇:Visual C#2005中使用正则表达式  
下一篇:在Vista中编程控制防火墙设定
相关信息:


Copyright © 2002-2015 版权所有
学校地址:北京市海淀区西三旗建材城中路29号北大青鸟
招生热线:010-82011433/32 京公网安备110102004704  京ICP备05043413号 京公网安备110102004704