Установка самописных компонентов (part II)

Jan 20, 2010 17:58

Начало

Получить ссылку на VS
Я предлагаю реализовать это как метод, который будет принимать DTE (главный объект в модели автоматизации студии) версию и флаг, который будет показывать

запущена студия или нет.

copy to clipboardподсветка кода
  1. (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.9.0")


Этот код применим для VS2008. Если вы захотите установить свои компоненты в несколько студий, я советую создать нумератор, где

будут перечислены все возможные варианты.

copy to clipboardподсветка кода
  1. [Flags]  
  2. public enum DTEVersion

    {  
  3.      None = 0x0000,  
  4.      [Description("VisualStudio.DTE.9.0")]  
  5.      VS2008 = 0x0001,  
  6.      [Description("VisualStudio.DTE.8.0")]  
  7.      VS2005 = 0x0002,  
  8.      [Description("VisualStudio.DTE.7.0")]  
  9.      VS2003 = 0x0004,  
  10.      [Description("VisualStudio.DTE.10.0")]  
  11.      VS2010 = 0x0008,  
  12. }  

Использование нумераторов делает код более гибким. Можно не делать проверку на соответствие строк, к тому же RegisterControls так

же может принимать DTEVersion. Внутри метода RegisterControls можно будет написать тогда так:

copy to clipboardподсветка кода
  1. public static void RegisterControls(DTEVersion dteVersion, params VSControl[] controls) {  
  2.     DTE2 dte = null;  
  3.     var alreadyCreated = false;  
  4.   
  5.     if ((dteVersion & DTEVersion.VS2008) > DTEVersion.None) {  
  6.         dte = (DTE2)

    Marshal.GetActiveObject("VisualStudio.DTE.9.0");  
  7.         // other code  
  8.         ...  
  9.     }  
  10.   
  11.     if ((dteVersion & DTEVersion.VS2010) > DTEVersion.None) {  
  12.         dte = (DTE2)

    Marshal.GetActiveObject("VisualStudio.DTE.10.0");  
  13.         // other code  
  14.        ...  
  15.     }  
  16. }  

Появление в коде строковых переменных весьма странно, когда уже есть нумератор с описаниями. И вот способ как это можно

использовать:

copy to clipboardподсветка кода
  1. internal static string GetEnumDescription(Enum value) {  
  2.     var fieldInfo = value.GetType().GetField(value.ToString());  
  3.     var attributes = (DescriptionAttribute[])

    fieldInfo.GetCustomAttributes(typeof

    (DescriptionAttribute), false);  
  4.     return (attributes.Length > 0) ? attributes

    [0].Description : value.ToString

    ();  
  5. }  

И тогда получение ссылки на студию

copy to clipboardподсветка кода
  1. dte = (DTE2)Marshal.GetActiveObject("VisualStudio.DTE.9.0");  

можно переписать следующим образом:

copy to clipboardподсветка кода
  1. dte = GetDesignTimeEnvironment(DTEVersion.VS2008, ref alreadyCreated);  

в новом методе мы проверим еще кое-что. Когда вы получаете DTE2, это занимает некоторое время для того, чтобы СОМ-метод вызвался и

вернул результат. После этого, было бы неплохо проверить, что ссылка на студию действительно получена, и попробовать переключится

на какой-нибудь базовый экран, к примеру, на окно свойств.

copy to clipboardподсветка кода
  1. public static DTE2 GetDesignTimeEnvironment

    (DTEVersion dteVersion, ref bool alreadyCreated)

    {  
  2.     alreadyCreated = false;  
  3.   
  4.     var progID = GetEnumDescription

    (dteVersion);  
  5.     DTE2 result;  
  6.   
  7.     try {  
  8.         result = (DTE2)

    Marshal.GetActiveObject(progID);  
  9.         Thread.Sleep(5000);  
  10.         try {  
  11.              result.ExecuteCommand("View.PropertiesWindow", "");  
  12.              alreadyCreated = true;  
  13.         }  
  14.         catch  {  
  15.              result = null;  
  16.         }  
  17.     }  
  18.     catch {   //There is no open VS.Net  
  19.         result = null;  
  20.     }  
  21.   
  22.     return result;  
  23. }  

Осталось проверить результат на null и если не null, то создаем новую панель.

Получение указателя на панель инструментов

Вы будете удивлены, но это очень легко! Всего 2 строчки кода.

copy to clipboardподсветка кода
  1. var toolbox = dte.Windows.Item(Constants.vsWindowKindToolbox);  
  2. var tabs = ((ToolBox)

    toolbox.Object).ToolBoxTabs;  

Создание новой панели

Так как компоненты и новая панель уже должны быть обернуты в VSControl - новый метод должен принимать массив этого класса. Ищем в

массиве объявления панелей и создаем их.

copy to clipboardподсветка кода
  1. internal static void RegisterControls(DTE2 dte, bool alreadyCreatedDTE, VSControl[] controls)

    {  
  2.     var toolbox = dte.Windows.Item

    (Constants.vsWindowKindToolbox);  
  3.     var tabs = ((ToolBox)

    toolbox.Object).ToolBoxTabs;  
  4.     controls  
  5.         .ToList()  
  6.         .FindAll

    (i => i.IsToolBoxTab)  
  7.         .ForEach(i => {  
  8.                  var tab =&nb

    sp;GetToolBoxTab(tabs, i.TabName);  
  9.                  if (tab != null)  
  10.                     &nbs

    p;tab.Delete();  
  11.                  tabs.Add

    (i.TabName);  
  12.                  });  
  13. }  
  14.   
  15. private static ToolBoxTab3 GetToolBoxTab(ToolBoxTabs tabs, string tabName) {  
  16.     foreach (ToolBoxTab3 tab in tabs) {  
  17.         if (smenglish.CompareInfo.Compare

    (tab.Name, tabName,  CompareOptions.IgnoreCase) == 0)  
  18.             return tab;  
  19.     }  
  20.   
  21.     return null;  
  22. }  

И поле класса:

copy to clipboardподсветка кода
  1. internal static CultureInfo smenglish = CultureInfo.CreateSpecificCulture

    ("en");  


Читать полностью на Violet Tape или часть III
Previous post Next post
Up