VS.Net插件制作初级教程
2007-08-29 17:37
465 查看
[align=left]VS.Net插件制作初级教程 作者:东方蜘蛛 2002年5月[/align] | |||
概述: 本文假定您对C#、VB.Net、CLR等有一定的了解,并具备一些基本的编码知识 不管微软目前的VS.NET IDE工具有多强大,但是对开发人员而言,总有一些自己希望有的功能却没有具备,出于这点考虑,VS.Net IDE提供了一个易用的工具,允许开发人员拓展自己所需的功能,这也就是我们今天所提的插件,插件的制作非常简单,而且可以使用任何.Net支持的语言如VB、C#、C、C++等等,本文描述了插件的工作方式,将通过建立一个文本编辑插件实例来展示。它有一个简单的功能:在当前文本里插入当前日期。 如果您目前已经开始使用微软VS.Net的RTM版本,您肯定知道微软在这个工具里包装了很多新的功能和工具,对于一个代码编辑工具而言,那实在是没什么地方可以挑剔了,可惜开发人员眼中几乎没有十全十美的这方面的工具,原因无他,很多人都希望这个开发工具包含了自己想象的功能,可是微软也做不到这一点,幸好它留了让开发人员自由发挥的空间,我想这点已经足够了。好了,现在让我们开始吧。 开始 插件和宏都有扩展IDE的能力,对于插件而言,由于是被编译的,一旦发布就无法被修改,因而保护了自己的知识产权。插件能做到与IDE的无逢嵌合,比如可以定义自己的工具栏,修改菜单命令的状态,甚至可以帮助下的ABOUT对话框中加上自己个性化的东西。有关创建一个插件的详细步骤可以在微软的站点里找到,也可以查看SDK里的帮助,里面也有详细的介绍,由于是向导式的,这里,我只重复一些关键性的步骤。 1、 打开MicroSoft Visual Studio .Net工具,新建一扩展性项目,取名为TextUtil,如下图所示。这里假定你使用的是中文版本。 2、 点击确定以后会开始出现欢迎向导页面,点下一步选择使用的语言,这里我们选择C#,再下一步选择支持的应用程序,选好以后继续点击下一步设定名称和说明,接着出现如下页面设定外接程序(插件)的选项。 设置好以后继续下一步,设置“帮助”中的“关于”信息,最后单击完成,我们的向导操作就大功告成了。 3、 接下来向导会自动创建一个Connect.cs文件,让我们来看一下里面的东东 (1)Connect::Connect 这个构造函数用于您的简单的初始化。 (2)Connect::OnConnection 这个方法是在IDE装载您创立的ADD-IN的时候执行的,您应该在这里初始化您的插件,告诉IDE你创建的命令,指定键盘绑定等等。 (3)Connect::QueryStatus IDE调用这个命令以知道当前哪个命令合适,根据不同的情况做不同的响应。 (4)Connect:Exec IDE用这个命令来执行您刚刚所创建的命令。 这里我们创建一个简单的命令:InsertDate,这个命令的用途是在当前光标的位置插入当前的日期,.Net包含了一个同样功能的宏示例,这样,您可以看到他们的异曲同工之妙。这个命令很简单,您只要稍微修改一下头上所示的Exec函数里的东西就可以了。 我们把 handled = true; 替换成 handled = InsertDate(); 然后实现如下InsertDate的代码: // InsertDate // Insert the current date in my favorite format. // bool InsertDate() { if (null != applicationObject.ActiveDocument) ((TextSelection)applicationObject.ActiveDocument.Selection).Text = DateTime.Now.ToString("dd-MMM-yyyy"); return true; } 虽然很简单,但这的确就是一个插件了 现在我们就可以运行它了,按一下F5,我们看到启动了一个新的IDE实例。点击工具——》外接程序管理器,弹出如下窗口。 选择文本编辑插件左边的复选框,点确定以后装载插件。 现在我们可以让它为我们做点事情了,随意打开一个工程,打开一个代码文件,按Ctrl+Alt+A调出命令窗口,IDE提供了自动完成的功能,打一个Te以后就会出现如下界面: 按一下回车,看到了什么?在当前位置插入了当前日期了吧,呵呵。(未完待续) VS.Net插件制作进阶教程 本文将通过一个实例来展现复杂的插件的制作方式,本实例是模拟用户的DOS环境,出发点是当我们在制作控制台输出程序的时候,有时候没看清楚结果屏幕就关闭了,当然我们有一些其他的解决办法,比如让程序继续等待等等,但这里,我们只做演示用,您可以自己扩展它,:) 如果您看过VS.Net插件制作的初级教程,那对你理解本文将产生帮助,如果没有,您也可以通过自己的实践来达到初级教程的目的。 我们先新建一个名为Command的ADD-IN工程。如果您对这个步骤不熟悉,请看一下初级教程。 现在我们建立一个用户控件,如左下图排版样式。注意,下图是运行以后的样式,为了省空间,所以直接拿过来了。 来看代码吧,来看关键的执行命令的代码。 [align=left]private void Start()[/align] [align=left] {[/align] [align=left] Process p = new Process();[/align] [align=left] StreamWriter sw;[/align] [align=left] StreamReader sr;[/align] [align=left] StreamReader err; [/align] [align=left] ProcessStartInfo psI = new ProcessStartInfo("cmd");[/align] [align=left] psI.UseShellExecute = false;[/align] [align=left] psI.RedirectStandardInput = true;[/align] [align=left] psI.RedirectStandardOutput = true;[/align] [align=left] psI.RedirectStandardError = true;[/align] [align=left] psI.CreateNoWindow = true;[/align] [align=left] p.StartInfo = psI; p.Start();[/align] [align=left] sw = p.StandardInput;[/align] [align=left] sr = p.StandardOutput;[/align] [align=left] err = p.StandardError; sw.AutoFlush = true;[/align] [align=left] if (this.txtCommandname.Text != "")[/align] [align=left] {[/align] [align=left] //切换到当前目录[/align] [align=left] sw.WriteLine("cd "+this.txtPathInfo.Text);[/align] [align=left] sw.WriteLine(this.localdrive);[/align] [align=left] sw.WriteLine(this.txtCommandname.Text);[/align] [align=left] }[/align] [align=left] else[/align] [align=left] //execute default command[/align] [align=left] sw.WriteLine("dir c://"); [/align] [align=left] sw.Close();[/align] [align=left] this.txtResult.AppendText(sr.ReadToEnd());[/align] [align=left] this.txtResult.AppendText(err.ReadToEnd()); [/align] } [align=left] public void SetCommandInfo(string strPath)[/align] [align=left] {[/align] [align=left] int endposition = strPath.LastIndexOf("//");[/align] [align=left] int startposition = strPath.IndexOf("//",0,strPath.Length); [/align] [align=left] string path = strPath.Substring(0,endposition);[/align] [align=left] string filename = strPath.Substring(endposition+1);[/align] [align=left] this.txtPathInfo.Text = path;[/align] [align=left] this.txtCommandname.Text = filename; [/align] [align=left] this.localdrive = strPath.Substring(0,startposition);[/align] } 点击执行以后就是执行Start这个函数,关于PROCESS的更详细的信息请看一下MSDN里的帮助,这里我们看到程序利用了CMD作为入口,就象在开始菜单——运行里面打CMD一样,接着程序利用DOS命令切换到当前目录,然后执行程序,最后再是读出程序的执行结果,总而言之,这部分代码比较简单。 另外一个函数是做改变当前程序设置用的。 接下来看我们这次的主体Connect.CS里的东西 [align=left]public void Exec(string commandName, EnvDTE.vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled)[/align] [align=left] {[/align] [align=left] handled = false;[/align] [align=left] if(executeOption == EnvDTE.vsCommandExecOption.vsCommandExecOptionDoDefault)[/align] [align=left] {[/align] [align=left] if(commandName == "Command.Connect.Command")[/align] [align=left] {[/align] [align=left] if (this.doscommand == null)[/align] [align=left] {[/align] [align=left] this.ShowWindow();[/align] [align=left] }[/align] [align=left] else[/align] [align=left] {[/align] [align=left] this.window.Activate();[/align] [align=left] }[/align] [align=left] handled = true;[/align] [align=left] return;[/align] [align=left] }[/align] [align=left] }[/align] } 这个是主体程序,可以看到主要是根据当前控件是否已经实例化来决定是否执行ShowWindow函数,如果已经是的话,将直接调用装载控件的窗体。这里的doscommand就是刚刚我们创建的控件的一个引用。 [align=left]private void ShowWindow()[/align] [align=left] {[/align] [align=left] object objTemp = null;[/align] [align=left] try[/align] [align=left] {[/align] [align=left] string guid = "{C7520611-4791-41a9-9AE8-178F78844C2E}";[/align] [align=left] window = applicationObject.Windows.CreateToolWindow(addInInstance,"EastSpider.Command.DOSCommand","EastSpider.Command.DOSCommand",guid,ref objTemp); [/align] [align=left] if (window.IsFloating)[/align] [align=left] {[/align] [align=left] window.Height = 700;[/align] [align=left] window.Width = 800;[/align] [align=left] } [/align] [align=left] AddToMainWindow(window);[/align] [align=left] window.Visible = true; [/align] [align=left] selectionEvents = (EnvDTE.SelectionEvents)applicationObject.Events.SelectionEvents;[/align] [align=left] selectionEvents.OnChange += new EnvDTE._dispSelectionEvents_OnChangeEventHandler(this.SelectionOnChange); [/align] [align=left] this.doscommand = (EastSpider.Command.DOSCommand)objTemp;[/align] [align=left] } [/align] [align=left] catch[/align] [align=left] {[/align] [align=left] }[/align] } [align=left]private void AddToMainWindow(Window win)[/align] [align=left] {[/align] [align=left] Window mainWindow = applicationObject.MainWindow;[/align] [align=left] Windows windows = applicationObject.Windows;[/align] [align=left] LinkedWindows lw = mainWindow.LinkedWindows;[/align] [align=left] if ( lw != null ) [/align] [align=left] {[/align] [align=left] if ( win.AutoHides != true)[/align] [align=left] lw.Add(win);[/align] [align=left] }[/align] } 这两段程序建立了装载控件的窗体,并自动“靠边隐藏”,:) [align=left]private bool IsExeFileSelected() { EnvDTE.SelectedItems selectedItems = applicationObject.SelectedItems;[/align] [align=left] EnvDTE.SelectedItem selectedItem = selectedItems.Item(1); [/align] [align=left] if ( selectedItem == null )[/align] [align=left] return false;[/align] [align=left] EnvDTE.ProjectItem projectItem = selectedItem.ProjectItem;[/align] [align=left] if ( projectItem == null )[/align] [align=left] return false;[/align] [align=left] string fullName = projectItem.get_FileNames(1);[/align] [align=left] string ext = System.IO.Path.GetExtension(fullName);[/align] [align=left] if (string.Compare(ext, ".exe", true) != 0)[/align] [align=left] return false;[/align] [align=left] else[/align] [align=left] return true;[/align] [align=left] } [/align] [align=left] private void SelectionOnChange()[/align] [align=left] {[/align] [align=left] if ( ( applicationObject.SelectedItems.Count == 1 ) && IsExeFileSelected())[/align] [align=left] {[/align] [align=left] window.Visible = true;[/align] [align=left] doscommand.SetCommandInfo(applicationObject.SelectedItems.Item(1).ProjectItem.get_FileNames(1));[/align] [align=left] }[/align] } 这两段代码是判断当前是否选择了唯一的可执行文件,如果是,把参数传递给控件类里用于改变当前默认设置,这样,就做到了用户只需选择文件,程序就可自动做出反应。 注意:出于程序的需要(Connect.cs里创建窗体的时候),我给控件类指定了ProgId 和 Guid,如下: [align=left][ProgId("EastSpider.Command.DOSCommand"),Guid("C7520611-4791-41a9-9AE8-178F78844C2E")][/align] public class DOSCommand : System.Windows.Forms.UserControl ……. 将命名空间与类型名组合在一起可以为类自动生成 ProgId。然而,这可能产生无效的 ProgId,具体的信息请参考一下MSDN吧。 由于代码比较多,这里不能一一全部奉上了,以上的代码已经完全能实现我所说的功能了,剩下的一些零碎的东西我相信大家自己补充一下肯定不成问题,关于公共环境对象模型(EnvDTE 类型库)等相关的信息,请大家还是参考一下MSDN里面的东西,由于大部分代码都是自动生成的,我们所要的只是引用而已,我也不介绍了。我会在适当的时间发布整个工程,请关注http://www.dev-club.com/club/bbs/main.asp?boardid=115,关于工程的实例,请到这里下载ftp://devclub:devclub@202.106.155.102/,关于插件的更多资源,请参考这里http://msdn.microsoft.com/vstudio/downloads/automation.asp,希望这两个实例能对你有些帮助,我是东方蜘蛛。 |
相关文章推荐
- VS.Net插件制作初级教程
- 40款非常棒的 jQuery 插件和制作教程(系列一)
- asp.net动态网页制作视频教程
- Highcharts插件制作中文教程
- 制作Vs.net 2010 c# 引用vSphere Web Services sdk5.0的dll
- [译]Godot系列教程五 - 制作Godot编辑器插件
- Discuz!X 插件制作教程 ------ 页面嵌入 & 导航
- VS安装部署制作教程(1)
- Atom 插件制作教程
- 插件__[手把手教]【整理一些discuz插件开发制作入门级教程】
- 在WinForm和WPF中使用GMap.Net地图插件简单教程
- 使用VS.NET开发Web Services 简明教程
- C#制作ActiveX浏览器插件.net
- vs.net应用程序图标以及制作安装程序快捷方式图标设置
- Discuz!X 插件制作教程(一) ------ 网站基本数据
- SVN的VS.NET插件——AnkhSVN
- 采用Reflector的VS.net插件断点调试无源码DLL
- adobe 扩展面板制作教程(初级)
- 循序渐进做项目系列(5):制作安装包,谁人都可以!——VS制作安装包简明教程
- VS.net 安装包制作