Connect.cs 最重要的类。注释的方法都在里面
/// <summary>用于实现外接程序的对象。</summary> public class Connect : IDTExtensibility2, IDTCommandTarget { /// <summary>实现外接程序对象的构造函数。请将您的初始化代码置于此方法内。</summary> public Connect() { } /// <summary>实现 IDTExtensibility2 接口的 OnConnection 方法。接收正在加载外接程序的通知。</summary> /// <param term='application'>宿主应用程序的根对象。</param> /// <param term='connectMode'>描述外接程序的加载方式。</param> /// <param term='addInInst'>表示此外接程序的对象。</param> /// <seealso class='IDTExtensibility2' /> 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; string toolsMenuName; try { // 添加在菜单栏里面 // CommandBar.resx. ResourceManager resourceManager = new ResourceManager("StarkingCommentTool.CommandBar", Assembly.GetExecutingAssembly()); CultureInfo cultureInfo = new System.Globalization.CultureInfo(_applicationObject.LocaleID); string resourceName = String.Concat(cultureInfo.TwoLetterISOLanguageName, "Tools"); toolsMenuName = resourceManager.GetString(resourceName); } catch { toolsMenuName = "Tools"; } //将此命令置于“工具”菜单上。 //查找 MenuBar 命令栏,该命令栏是容纳所有主菜单项的顶级命令栏: Microsoft.VisualStudio.CommandBars.CommandBar menuBarCommandBar = ((Microsoft.VisualStudio.CommandBars.CommandBars)_applicationObject.CommandBars)["MenuBar"]; //在 MenuBar 命令栏上查找“工具”命令栏: CommandBarControl toolsControl = menuBarCommandBar.Controls[toolsMenuName]; CommandBarPopup toolsPopup = (CommandBarPopup)toolsControl; //如果希望添加多个由您的外接程序处理的命令,可以重复此 try/catch 块, // 只需确保更新 QueryStatus/Exec 方法,使其包含新的命令名。 try { //将一个命令添加到 Commands 集合: Command commandA = commands.AddNamedCommand2(_addInInstance, "Add", "Add", "Add Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); Command commandD = commands.AddNamedCommand2(_addInInstance, "Del", "Del", "Delete Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); Command commandC = commands.AddNamedCommand2(_addInInstance, "Chg", "Chg", "Change Comment", true, 59, ref contextGUIDS, (int)vsCommandStatus.vsCommandStatusSupported + (int)vsCommandStatus.vsCommandStatusEnabled, (int)vsCommandStyle.vsCommandStylePictAndText, vsCommandControlType.vsCommandControlTypeButton); //将对应于该命令的控件添加到“工具”菜单: if ((commandA != null) && (commandD != null) && (commandC != null) && (toolsPopup != null)) { commandA.AddControl(toolsPopup.CommandBar, 1); commandD.AddControl(toolsPopup.CommandBar, 1); commandC.AddControl(toolsPopup.CommandBar, 1); } } catch (System.ArgumentException) { //如果出现此异常,原因很可能是由于具有该名称的命令 // 已存在。如果确实如此,则无需重新创建此命令,并且 // 可以放心忽略此异常。 } } } /// <summary>实现 IDTExtensibility2 接口的 OnDisconnection 方法。接收正在卸载外接程序的通知。</summary> /// <param term='disconnectMode'>描述外接程序的卸载方式。</param> /// <param term='custom'>特定于宿主应用程序的参数数组。</param> /// <seealso class='IDTExtensibility2' /> public void OnDisconnection(ext_DisconnectMode disconnectMode, ref Array custom) { } /// <summary>实现 IDTExtensibility2 接口的 OnAddInsUpdate 方法。当外接程序集合已发生更改时接收通知。</summary> /// <param term='custom'>特定于宿主应用程序的参数数组。</param> /// <seealso class='IDTExtensibility2' /> public void OnAddInsUpdate(ref Array custom) { } /// <summary>实现 IDTExtensibility2 接口的 OnStartupComplete 方法。接收宿主应用程序已完成加载的通知。</summary> /// <param term='custom'>特定于宿主应用程序的参数数组。</param> /// <seealso class='IDTExtensibility2' /> public void OnStartupComplete(ref Array custom) { ReadConf(); } /// <summary>实现 IDTExtensibility2 接口的 OnBeginShutdown 方法。接收正在卸载宿主应用程序的通知。</summary> /// <param term='custom'>特定于宿主应用程序的参数数组。</param> /// <seealso class='IDTExtensibility2' /> public void OnBeginShutdown(ref Array custom) { } /// <summary>实现 IDTCommandTarget 接口的 QueryStatus 方法。此方法在更新该命令的可用性时调用</summary> /// <param term='commandName'>要确定其状态的命令的名称。</param> /// <param term='neededText'>该命令所需的文本。</param> /// <param term='status'>该命令在用户界面中的状态。</param> /// <param term='commandText'>neededText 参数所要求的文本。</param> /// <seealso class='Exec' /> public void QueryStatus(string commandName, vsCommandStatusTextWanted neededText, ref vsCommandStatus status, ref object commandText) { if (neededText == vsCommandStatusTextWanted.vsCommandStatusTextWantedNone) { switch (commandName) { case "StarkingCommentTool.Connect.Add": goto case "StarkingCommentTool.Connect.Chg"; case "StarkingCommentTool.Connect.Del": goto case "StarkingCommentTool.Connect.Chg"; case "StarkingCommentTool.Connect.Chg": status = (vsCommandStatus)vsCommandStatus.vsCommandStatusSupported | vsCommandStatus.vsCommandStatusEnabled; return; } } } private DTE2 _applicationObject; private AddIn _addInInstance; private string _add1 = "";//before add private string _add2 = "";//after add private string _del1 = "";//before del private string _del2 = "";//after del private string _changeBefore1 = "";//change before private string _changeAfter2 = "";//change after private string _changeDel = "";// comment /// private bool _autoCopy = true;//复制 private void ReadConf() { try { string strPath = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + @"\Visual Studio 2012\Addins\StarkingCommentTool.conf"; string strUserName = Environment.UserName; string strDateFormat = "yyyy.MM.dd"; string strAddFormatA = "NES Add {0} {1}"; string strAddFormatB = "NES Add {0} {1}"; string strDelFormatA = "NES Del {0} {1}"; string strDelFormatB = "NES Del {0} {1}"; string strCgAFormatB = "NES Change After {0} {1}"; string strCgBFormatA = "NES Change Before {0} {1}"; string strAllA = ""; string strAllB = ""; string strAddA = ""; string strAddB = ""; string strDelA = ""; string strDelB = ""; string strCgAB = ""; string strCgBA = ""; string strComm = ""; if (!File.Exists(strPath)) { System.Windows.Forms.MessageBox.Show("Starking_comment_tool can't read config file \rplease check it exist!", "Starking_comment_tool Error"); } else { XmlDocument xd = new XmlDocument(); xd.Load(strPath); XmlNode root = xd.ChildNodes[1]; //取出XML配置文件里面的自定义内容 strAddFormatA = root.SelectSingleNode("/config/before/add").InnerText; strDelFormatA = root.SelectSingleNode("/config/before/del").InnerText; strCgBFormatA = root.SelectSingleNode("/config/before/changeBefore").InnerText; strAddFormatB = root.SelectSingleNode("/config/after/add").InnerText; strDelFormatB = root.SelectSingleNode("/config/after/del").InnerText; strCgAFormatB = root.SelectSingleNode("/config/after/changeAfter").InnerText; strComm = root.SelectSingleNode("/config/comment").InnerText + " "; _changeDel = strComm; strDateFormat = root.SelectSingleNode("/config/dateFormat").InnerText + " "; ////////////////////////////////////////////////////////////////////////////// //取出XML配置文件节点other里面的自定义内容 strAllA = root.SelectSingleNode("/config/other/before/all").InnerText; strAddA = root.SelectSingleNode("/config/other/before/add").InnerText; strDelA = root.SelectSingleNode("/config/other/before/del").InnerText; strCgBA = root.SelectSingleNode("/config/other/before/changeBefore").InnerText; strAllB = root.SelectSingleNode("/config/other/after/all").InnerText; strAddB = root.SelectSingleNode("/config/other/after/add").InnerText; strDelB = root.SelectSingleNode("/config/other/after/del").InnerText; strCgAB = root.SelectSingleNode("/config/other/after/changeAfter").InnerText; string strAutoCopy = root.SelectSingleNode("/config/changeAutoCopy").InnerText; bool.TryParse(strAutoCopy, out _autoCopy); } string strDate = DateTime.Now.ToString(strDateFormat); //add _add1 = strComm + string.Format(strAddFormatA, strDate, strUserName) + strAddA + strAllA + Environment.NewLine; _add2 = strComm + string.Format(strAddFormatB, strDate, strUserName) + strAddB + strAllB + Environment.NewLine; //change _changeBefore1 = strComm + string.Format(strCgBFormatA, strDate, strUserName) + strCgBA + strAllA + Environment.NewLine; _changeAfter2 = strComm + string.Format(strCgAFormatB, strDate, strUserName) + strCgAB + strAllB + Environment.NewLine; //delete _del1 = strComm + string.Format(strDelFormatA, strDate, strUserName) + strDelA + strAllA + Environment.NewLine; _del2 = strComm + string.Format(strDelFormatB, strDate, strUserName) + strDelB + strAllB + Environment.NewLine; } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } } /// <summary>实现 IDTCommandTarget 接口的 Exec 方法。此方法在调用该命令时调用。</summary> /// <param term='commandName'>要执行的命令的名称。</param> /// <param term='executeOption'>描述该命令应如何运行。</param> /// <param term='varIn'>从调用方传递到命令处理程序的参数。</param> /// <param term='varOut'>从命令处理程序传递到调用方的参数。</param> /// <param term='handled'>通知调用方此命令是否已被处理。</param> /// <seealso class='Exec' /> public void Exec(string commandName, vsCommandExecOption executeOption, ref object varIn, ref object varOut, ref bool handled) { handled = false; if (executeOption == vsCommandExecOption.vsCommandExecOptionDoDefault) { switch (commandName) { #region//StarkingCommentTool.Connect.Add case "StarkingCommentTool.Connect.Add": TextSelection ts = _applicationObject.ActiveDocument.Selection as TextSelection; int TopLine = ts.TopPoint.Line; int ButtomLine = ts.BottomPoint.Line; bool ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine; int startLine = 0; int endLine = 0; if (TopLine == ButtomLine) { ts.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, false); ts.Insert(_add1, 0); ts.SmartFormat(); ts.LineDown(false, 1); ts.StartOfLine(vsStartOfLineOptions.vsStartOfLineOptionsFirstColumn, false); ts.Insert(_add2, 0); ts.SmartFormat(); ts.GotoLine(TopLine + 2, false); } else { if (ts.TopPoint.AtEndOfLine) { ts.GotoLine(TopLine + 1, false); ts.Insert(_add1, 0); } else { ts.GotoLine(TopLine, false); ts.Insert(_add1, 0); } ts.SmartFormat(); if (ButtomAtStartOfLine) { ts.GotoLine(ButtomLine + 1, false); ts.Insert(_add2, 0); } else { ts.GotoLine(ButtomLine + 2, false); ts.Insert(_add2, 0); } ts.SmartFormat(); } handled = true; return; #endregion #region//StarkingCommentTool.Connect.Del case "StarkingCommentTool.Connect.Del": ts = _applicationObject.ActiveDocument.Selection as TextSelection; TopLine = ts.TopPoint.Line; ButtomLine = ts.BottomPoint.Line; ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine; // Area Delete if (ts.TopPoint.AtEndOfLine) { ts.GotoLine(TopLine + 1, false); startLine = TopLine + 2; ts.Insert(_del1, 0); } else { ts.GotoLine(TopLine, false); startLine = TopLine + 1; ts.Insert(_del1, 0); } if (ButtomAtStartOfLine) { ts.GotoLine(ButtomLine + 1, false); endLine = ButtomLine; ts.Insert(_del2, 0); } else { ts.GotoLine(ButtomLine + 2, false); endLine = ButtomLine + 1; ts.Insert(_del2, 0); } for (int line = startLine; line < endLine + 1; line++) { ts.GotoLine(line, false); ts.SelectLine(); if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { ts.Insert(ts.Text.TrimStart(" ".ToCharArray()), 0); } if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { ts.Insert(_changeDel + ts.Text.TrimStart(" ".ToCharArray()), 0); } } //缩放注释到多少列 start==>end ts.GotoLine(TopLine, false); //计算选中的行数来进行注释 if (TopLine == ButtomLine) { //单行删除注释 ts.LineDown(true, ButtomLine + 3 - TopLine); } else { //多行删除注释 ts.LineDown(true, ButtomLine + (endLine + 1 - startLine) - TopLine); } ts.SmartFormat(); handled = true; return; #endregion #region//StarkingCommentTool.Connect.Chg case "StarkingCommentTool.Connect.Chg": ts = _applicationObject.ActiveDocument.Selection as TextSelection; TopLine = ts.TopPoint.Line; ButtomLine = ts.BottomPoint.Line; ButtomAtStartOfLine = ts.BottomPoint.AtStartOfLine; int intCount = ts.TextRanges.Count; if (TopLine == ButtomLine)//单行变更 { ts.GotoLine(TopLine, false); ts.SelectLine(); //选中要变化的内容 string strText = string.Empty; if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { strText = ts.Text.TrimStart(" ".ToCharArray()); } if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { strText = ts.Text.TrimStart(" ".ToCharArray()); } string strText2 = _changeBefore1 + _changeDel + strText.Replace(" ", ""); //复制要变更的内容 if (_autoCopy) strText2 += strText; else strText2 += Environment.NewLine; strText2 += _changeAfter2; //插入变更内容 ts.Insert(strText2, 0); ts.GotoLine(TopLine, false); //单行删除注释 ts.LineDown(true, ButtomLine + 4 - TopLine); ts.SmartFormat(); } else//多行内容变更 { if (!ts.TopPoint.AtEndOfLine && !ButtomAtStartOfLine) { intCount++; } if (ts.TopPoint.AtEndOfLine) { ts.GotoLine(TopLine + 1, false); startLine = TopLine + 2; ts.Insert(_changeBefore1, 0); } else { ts.GotoLine(TopLine, false); startLine = TopLine + 1; ts.Insert(_changeBefore1, 0); } if (ButtomAtStartOfLine) { ts.GotoLine(ButtomLine + 1, false); endLine = ButtomLine; } else { ts.GotoLine(ButtomLine + 2, false); endLine = ButtomLine + 1; } //存放选中变化的内容 StringBuilder sb = new StringBuilder(); if (_autoCopy) { for (int line = startLine; line < endLine + 1; line++) { ts.GotoLine(line, false); ts.SelectLine(); sb.Append(ts.Text); } } //循环注释掉选中的内容 for (int line = startLine; line < endLine + 1; line++) { ts.GotoLine(line, false); ts.SelectLine(); if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { ts.Insert(ts.Text.TrimStart(" ".ToCharArray()), 0); } if (ts.Text.Contains(" ") || ts.Text.Contains("{") || ts.Text.Contains("}") || ts.Text.Contains("//") || !ts.Text.Contains("///") || !ts.Text.Contains("#region") || !ts.Text.Contains("#endregion")) { ts.Insert(_changeDel + ts.Text.TrimStart(" ".ToCharArray()), 0); } } //复制选中的内容到计算好的行数中 ts.GotoLine(endLine + 1, false); if (_autoCopy) { ts.Insert(sb.ToString(), 0); ts.GotoLine(endLine + intCount, false); } else { ts.NewLine(1); } //插入注释结束语句 ts.Insert(_changeAfter2, 0); ts.GotoLine(TopLine, false); //计算行数光标停止在最后一行+1行 ts.LineDown(true, (endLine + intCount + 1) - TopLine); ts.SmartFormat(); } handled = true; return; #endregion } } } }
StarkingCommentTool.AddIn 创建自动产生的里面放外接程序的信息
<?xml version="1.0" encoding="UTF-16" standalone="no"?> <Extensibility xmlns="http://schemas.microsoft.com/AutomationExtensibility"> <HostApplication> <Name>Microsoft Visual Studio</Name> <Version>11.0</Version> </HostApplication> <Addin> <FriendlyName>StarkingCommentTool</FriendlyName> <Description>C# VC VB.NET JS 注释工具</Description> <Assembly>StarkingCommentTool.dll</Assembly> <FullClassName>StarkingCommentTool.Connect</FullClassName> <LoadBehavior>5</LoadBehavior> <CommandPreload>1</CommandPreload> <CommandLineSafe>1</CommandLineSafe> </Addin> </Extensibility>
<?xml version="1.0" encoding="utf-8" ?> <config> <!-- add: 追加 del: 削除 changeAfter: 変更前 changeBefore: 変更後 {0}: 时间格式化 NOTE: 请不要删除此文件中的注释(重要都是配置节点) --> <before> <!-- 変更前的应用 --> <add>{0}1处System对应 INSERT START</add> <del>{0}1处System对应 DELETE START</del> <changeBefore>{0}1处System对应 UPDATE START</changeBefore> </before> <after> <!-- 変更后的应用 --> <add>{0}1处System对应 INSERT END</add> <del>{0}1处System对应 DELETE END</del> <changeAfter>{0}1处System对应 UPDATE END</changeAfter> </after> <!-- dateFormat:日期格式化 例: 日付 2012年12月25日 dateFormat: yyyy.MM.dd 注释中的格式为中 2012.12.25 。 --> <dateFormat>yy/MM/dd</dateFormat> <other> <!-- all: 追加,削除,変更前,変更后等最后要追加的文字。 add: 追加后最后要追加的文字。 del: 削除后最后要追加的文字。 changeAfter: 修改前最后要追加的文字。 changeBefore: 修改后変最后要追加的文字。 all的优先级是最低的 例如 other中, 如果添加了all和add的場合, 那么注释中就会显示other.add other.all的样子。 --> <before> <all></all> <add></add> <del></del> <changeBefore></changeBefore> </before> <after> <all></all> <add></add> <del></del> <changeAfter></changeAfter> </after> </other> <!-- 修改的内容是否复制--> <changeAutoCopy>True</changeAutoCopy> <!-- 注释 VB: ' C#: /// --> <comment>///</comment> </config>
先贴出代码,稍后我整理测试完毕打包上传。