visual_studio插件开发中的一些问题

来源:互联网 发布:知微公司 编辑:程序博客网 时间:2024/06/04 19:22

Visual Studio插件开发中的一些问题

写在最前

这篇文章与上一篇文章之间还是有一些关系的,我们需要在之前工作的基础之上,开发VS插件,使其能够使用Clang的静态检查的功能。不知道是不是因为VS上的插件不是很多的原因,网上关于VS插件开发的内容也并不是很多,当然我这是与Eclipse相比较。所以写这篇文章的目的是与大家分享一下我在开发VS插件中碰到的一些问题。当然,这个VS插件主要的功能并不是通过插件的代码实现的,所以碰到的问题相对来说也比较简单。

为了开发VS插件,首先要了解下VS的插件机制。VS插件有三种开发方式:宏、add-in、vs package。关于这三种方式的区别,网上的资料还是比较多的,这里就不详述了。我选择的是add-in方式,开发语言是C#。最近C#使的比较多,感觉这门语言还是比较强大的,.NET平台也是啥都能干。在开发插件之前,必须要安装SDK,这个可以在微软的官网上下载。关于如何创建一个add-in工程,网上也有相应的教程,图文并茂,还是很详细的,这里我也就不再重复说明了。

为了顺利开发VS插件,还是要对其所提供的接口要熟悉,最方便的自然是msdn上的文档了,而且这个是有中文的,看起来也比较方便。我使用的是VS 2013,能不能适用于其他版本的VS,这个我也不清楚。接下来就进入正题。

在插件中添加菜单

要想使用VS插件,需要点击相应的菜单。在创建完add-in工程之后,在模板中,已经将菜单写好了,默认的是在Tool下。如果想要创建新的菜单,可以依葫芦画瓢,按照模板中的代码来做就行,而且注释也很详细。不过在这里我们还是来分析下如何添加一个菜单的。

首先是在哪里添加菜单。

    public void OnConnection(...){        _applicationObject = (DTE)application;        _addInInstance = (AddIn)addInInst;        if(connectMode == ext_Connect.ext_cm_UISetup){            //添加菜单代码        }    }

接下来就是一些功能性代码。

    string toolsMenuName = "Tools";

这一句就是说明,我们的菜单是添加在哪一个顶级菜单(不知道这种说法准不准确)之下的。当然你也可以自己创建一个顶级菜单。

    Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBar)_applicationObject.CommandBars)["MenuBar"];

这一句代码的含义是在所有的主菜单中寻找到 Menubar command bar。

    CommandBarControl toolsControl_1 = menuCommandBar.Controls[toolsMenuName];    CommandBarPopup toolsPopup_1 = (CommandBarPopup)toolsControl_1;    Command command_1 = commands.AddNamedCommand2(_addInInstance,"button1","test","",...)

这三行代码的功能就是创建出一个菜单。其中第三行代码的第二个参数表示该菜单的标识符,第三个参数表示该菜单显示出的信息,第四个参数表示鼠标悬停在上面时所显示出的信息。之后还有一大堆的参数我就不一一列了,照抄就行。

之后还需要加上一段代码。

    if((command_1 != null) && (toolsPopup_1 != null)){        command_1.AddControl(toolsPopup_1.CommandBar,1);    } 

其实我也不懂该段代码的确切功能是啥。

我们的工作还并没有结束,还需要找到下面的代码的位置。

    public void QueryStatus(...){        if(needText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone){            //添加代码的位置        }    }

在相应的位置上添上这样一段代码。

    if(commandName == "xxx.Connect.button1"){        status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported|vsCommandStatus.vsCommandStatusEnabled;        return;    }

其中xxx表示工程的名字,button1表示之前你给该菜单所起的一个唯一的标识符的名字。

通过上述的分析想必也能了解到,创建的菜单都是在某一栏之下的,如果想添加一个菜单的子菜单,这我也不知道怎么做,如果有大神看到的话,欢迎指导。

编写功能代码

在新建好工程之后,里面的代码只有一个Connect类,和一些方法的代码。那我们插件的功能代码应该放在哪个位置呢?

    public void Exec(...){        handled = false;        if(executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault){            //插件的功能代码        }    }

如果我们要使用之前定义的某个菜单,则需要添加如下的一段代码。

    if(commandName == "xxx.Connect.button1"){        //添加你的功能代码        handled = true;        return;    }

获取当前打开的文件的路径

VS在编辑窗口中,可以通过打开多个选项卡的方式来打开多个源代码文件。那么如何获取当前打开的源代码文件的路径,或是其所在文件夹的路径呢?下面的代码就能够做到。

    Document doc = _applicationObject.ActiveDocument;    string path = doc.FullName;

第一行代码中的ActiveDocument,即活动文档,表示的就是当前所打开的代码文件。所获取到的是document类的对象,通过查看msdn上的文档可以发现,其内包含了很多的属性,可以获取到当前文件的各种信息。

如果在VS的编辑窗口中,并没有打开的代码文件,执行上述代码,会产生System.NullReferenceException异常。

在输出窗口进行输出

如果你的插件需要在输出窗口输出一些结果信息,可以这样来做:

    OutputWindow ow = _applicationObject.ToolWindows.OutputWindow;

首先获取输出窗口的对象。

    OutputWindowPane owp;    owp = ow.OutputWindiwPanes.Add("");

创建一个输出窗口的标签(我不知道这样描述的对不对),引号中填写该标签的名字。

    owp.OutputString();

这样就可以实现向输出窗口中输出信息。

在我做的插件中,就是将静态检查的结果进行输出。如果有相应的错误信息,希望能够跟VS编译代码一样,点击错误能够跳转到代码中相应的位置。但是在OutputWindowEvents中,并没有点击这个事件的接口,所以我也没有能够实现这一功能。不知道是不是姿势不对,还希望能够有大神来指导下。

在插件中添加窗口

因为我们使用的是C#来开发插件,故添加一个窗口还是比较方便的,如果用C++的话,估计是要哭瞎。首先右键项目名称,在菜单中寻找『添加』一栏,选择里面的『Windows窗体』一项。在窗体的代码中需要添加下面的一段。

    private DTE2 _applicationObject;    public DTE2 applicationObject{        get{ return _applicationObject; }        set{ this._applicationObject = value;}    }

同时还需要在最前添加上两条语句。

    using EnvDTE;    using EnvDTE80;

在插件中如果需要显示该窗口,需要加上:

    Form f = new Form();    f.applicationObject = _applicationObject;    f.Show();

其中Form表示给该窗体所取的名字。至于该窗体应如何设计,这里就不讨论了。

0 0