演练:自动上载的工具箱项

本演练阐释了托管 VSPackage 如何使用反射自动填充其自己的程序集中提供的所有 ToolboxItem 项目。

备注

建议使用此方法的方式将自定义控件添加到工具箱将使用随 Visual Studio 10 SDK,包括自动上载支持的工具箱控件模板。本主题保留以备向后兼容,用于将现有控件添加到工具箱和用于高级工具箱开发。

有关使用该模板创建的工具箱控件的更多信息,请参见 如何:创建使用 windows 窗体的一个工具箱控件如何:使用 WPF 创建一个工具箱控件

本演练将引导您完成以下步骤:

  1. 使用 ToolboxItemAttributeToolboxBitmapAttributeDisplayNameAttribute,添加和正确注册在 VSPackage 对象的所有 工具箱 控件。

  2. 创建以下两个控件,并将每个的图标。 工具箱:

    • 使用默认 ToolboxItem 类,添加一个控件。

    • 添加另一个控件通过使用 ToolboxItem 类派生的自定义类。

  3. 注册 VSPackage 为提供一 ProvideToolboxItemsAttribute 类的 ToolboxItem 对象。

  4. 生成 VSPackage 提供所有 ToolboxItem 对象的列表使用反射时加载。

  5. 创建 ToolboxInitializedToolboxUpgraded 事件的处理程序。 这样做是为了确保 VSPackage 中 ToolboxItem 对象能正确加载。

  6. 实现在 VSPackage 中的命令强制 工具箱的再预装。

系统必备

若要完成本演练,您必须安装 Visual Studio 2010 SDK。

备注

有关 Visual Studio SDK 的更多信息,请参见 扩展 Visual Studio 概述。若要查找有关中所列如何下载 Visual Studio SDK,请 Visual Studio Extensibility Developer Center 参见 MSDN 网站上。

Visual Studio 包 " 项目模板的位置

Visual Studio 包 " 项目模板可以在 新项目 对话框的三个不同位置找到:

  1. 在 Visual Basic 扩展性下。 该项的默认语言是 Visual Basic。

  2. 在 C# 扩展性下。 该项目的默认语言是 C#。

  3. 在其他项下键入扩展性。 该项的默认语言是 C++。

创建托管 VSPackage

创建 LoadToolboxMembers VSPackage

  1. 创建名为 LoadToolboxMembers的 VSPackage。 有关更多信息,请参见 演练:使用 Visual Studio 创建包模板的菜单命令

  2. 添加一个菜单命令。

    为 Visual Basic 或 初始化 LoadToolboxMembers cs 的命令 初始化 LoadToolboxMembers VB Visual C# 中。

如果您遵循多个语言的本演练,您必须更新项目包含生成的程序集。

消除 Visual Basic 和 Visual C# Vspackage

  1. 为 Visual Basic:

    • 在解决方案资源管理器中,打开项目属性,然后选择 应用程序 选项。

      更改程序集名称。 LoadToolboxMembersVB,并更改默认命名空间。 Company.LoadToolboxMembersVB。

  2. 为 Visual C#:

    1. 在解决方案资源管理器中,打开项目属性,然后选择 应用程序 选项。

      更改程序集名称。 LoadToolboxMembersCS,并更改默认命名空间。 Company.LoadToolboxMembersCS。

    2. 在代码编辑器中打开 LoadToolboxMembersPackage 类。

      若要使用重构工具给现有的命名空间重命名,右击现有的命名空间名称, LoadToolboxMembers,指向 重构,然后单击 重命名。 更改该名称。 LoadToolboxMembersCS。

  3. 保存所有更改。

若要添加支持引用

  1. 在 LoadToolboxMembers 项目中,添加对 System.Drawing.Design .NET framework 组件,如下所示。

    1. 解决方案资源管理器,右击 LoadToolboxMembers 项目,然后单击 添加引用

    2. 添加引用 对话框的 .NET 选项卡中,双击 System.Drawing.Design

  2. 对于 Visual Basic,添加以下命名空间到导入的命名空间列出项目:

    • Company.LoadToolboxMembersVB

    • 系统

    • System.ComponentModel

    • System.Drawing

    • System.Windows.Forms

测试生成的代码

  1. 生成并启动在 Visual Studio 的实验项的 VSPackage。

  2. 工具 菜单上,单击 初始化 LoadToolboxMembers VB初始化 LoadToolboxMembers cs

    这将打开包含文本指示的消息框包的菜单项处理程序。

  3. 关闭 Visual Studio的实验版本。

创建工具箱控件

在本节中,您创建和注册用户控件, Control1,声明一个关联的默认 工具箱 项目。 有关如何创作 windows 窗体控件和 ToolboxItem 类的更多信息,请参见 设计时开发 Windows 窗体控件

若要创建将用于默认 ToolboxItem 的工具箱控件

  1. 解决方案资源管理器,请向 LoadToolboxMembers 项目的一 UserControl 对象,如下所示:

    1. 解决方案资源管理器,右击 LoadToolboxMembers 项目,指向 添加,然后单击 用户控件

    2. 添加新项目 对话框中,将该名称。 Visual Basic 的 Visual C#的 Control1.vb 或 Control1.cs 。

      有关如何添加新项目的更多信息到项目中,请参见 How to: Add New Project Items

    新的控件在设计视图中打开。

  2. 工具箱,将 按钮 控件 (位于 公共控件 类别) 到设计器。

  3. 双击您创建的按钮。 执行此生成按钮的 Click 事件的事件处理程序。 使用以下代码,更新事件处理程序:

    Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
        Handles Button1.Click
    
        MessageBox.Show("Hello world from " & Me.ToString())
    End Sub
    
    private void button1_Click(object sender, EventArgs e)
    {
        MessageBox.Show("Hello world from " + this.ToString());
    }
    
  4. ,在 InitializeComponent 调用方法后,修改该控件的构造函数中设置按钮文本:

    Public Sub New()
    
        InitializeComponent()
    
        Button1.Text = Me.Name + " Button" 
    End Sub
    
    public Control1()
    {
        InitializeComponent();
    
        button1.Text = this.Name + " Button";
    }
    
  5. 将特性添加到文件使 VSPackage 查询所提供的 ToolboxItem 类:

    ' Set the display name and custom bitmap to use for this item. 
    ' The build action for the bitmap must be "Embedded Resource".
    <DisplayName("ToolboxMember 1 VB")> _
    <Description("Custom toolbox item from package LoadToolboxMembers.")> _
    <ToolboxItem(True)> _
    <ToolboxBitmap(GetType(Control1), "Control1.bmp")> _
    Public Class Control1
    
    // Set the display name and custom bitmap to use for this item. 
    // The build action for the bitmap must be "Embedded Resource".
    [DisplayName("ToolboxMember 1 CS")]
    [Description("Custom toolbox item from package LoadToolboxMembers.")]
    [ToolboxItem(true)]
    [ToolboxBitmap(typeof(Control1), "Control1.bmp")]
    public partial class Control1 : UserControl
    {
    
  6. 保存该文件。

在下面的过程中,您创建和注册第二个用户控件、 Control2与关联的自定义 工具箱 项目, Control2_ToolboxItem,从 ToolboxItem 类派生。

若要创建工具箱控件用于自定义 ToolboxItem 派生的类

  1. 创建第二个用户控件 Control2。 双击窗体使代码文件。

  2. 添加 System.Drawing.Design 和 System.Globalization 为在类的命名空间。

    Imports System.Drawing.Design
    Imports System.Globalization
    
    using System.Drawing.Design;
    using System.Globalization;
    
  3. 添加一个按钮和按钮单击事件处理程序并更新控件的构造函数与您更新的第一个控件。

  4. 添加 DisplayNameAttributeDescriptionAttributeToolboxItemAttributeToolboxBitmapAttribute 属性到文件。

    这些属性使 VSPackage 为 ToolboxItem 类查询。

    有关更多信息和示例有关如何编写自定义 ToolboxItem 对象,如何请参见讨论在 ToolboxItem 参考页。

    与前面的更改时,第二个控件类应类似于以下代码。 符号 Control2_ToolboxMenu 将为未定义在下一步之后。

    ' Set the display name and custom bitmap to use for Me item. 
    ' The build action for the bitmap must be "Embedded Resource". 
    ' Also declare a custom toolbox item implementation.
    <DisplayName("ToolboxMember 2 VB")> _
    <Description("Custom toolbox item from package LoadToolboxMembers.")> _
    <ToolboxItem(GetType(Control2_ToolboxItem))> _
    <ToolboxBitmap(GetType(Control2), "Control2.bmp")> _
    Public Class Control2
    
        Public Sub New()
            InitializeComponent()
    
            Button1.Text = Me.Name + " Button" 
        End Sub 
    
        Private Sub Button1_Click(ByVal sender As Object, ByVal e As EventArgs) _
            Handles Button1.Click
    
            MessageBox.Show("Hello world from " & Me.ToString())
        End Sub 
    End Class
    
    // Set the display name and custom bitmap to use for this item. 
    // The build action for the bitmap must be "Embedded Resource".
    // Also declare a custom toolbox item implementation.
    [DisplayName("ToolboxMember 2 CS")]
    [Description("Custom toolbox item from package LoadToolboxMembers.")]
    [ToolboxItem(typeof(Control2_ToolboxItem))]
    [ToolboxBitmap(typeof(Control2), "Control2.bmp")]
    public partial class Control2 : UserControl
    {
        public Control2()
        {
            InitializeComponent();
    
            button1.Text = this.Name + " Button";
        }
    
        private void button1_Click(object sender, EventArgs e)
        {
            MessageBox.Show("Hello world from " + this.ToString());
        }
    }
    
  5. 创建名为 Control2_ToolboxItem的类。 此 ToolboxItem 为第二个控件构造并将其添加到 工具箱。 类必须具有 SerializableAttribute 应用于它。

    <Serializable()> _
    Friend Class Control2_ToolboxItem
        Inherits ToolboxItem
    
        Public Sub New(ByVal toolType As Type)
            MyBase.New(toolType)
        End Sub 
    
        Public Overrides Sub Initialize(ByVal toolType As Type)
    
            If Not toolType.Equals(GetType(Control2)) Then 
                Throw New ArgumentException( _
                    String.Format(CultureInfo.CurrentCulture, _
                        "The {0} constructor argument must be of type {1}.", _
                        Me.GetType().FullName, GetType(Control2).FullName))
            End If 
    
            MyBase.Initialize(toolType)
        End Sub 
    End Class
    
    [Serializable()]
    internal class Control2_ToolboxItem : ToolboxItem
    {
        public Control2_ToolboxItem(Type toolType)
            : base(toolType) { }
    
        public override void Initialize(Type toolType)
        {
            if (!toolType.Equals(typeof(Control2)))
            {
                throw new ArgumentException(
                    string.Format(CultureInfo.CurrentCulture,
                        "The {0} constructor argument must be of type {1}.",
                        this.GetType().FullName, typeof(Control2).FullName));
            }
    
            base.Initialize(toolType);
        }
    }
    
  6. 保存该文件。

嵌入图标位图

ToolboxBitmapAttribute 两个实例使用了早期指示使用以下图标,该项表示两个控件:

  • Control1.bmp,位于包含第一个控件的命名空间。

  • Control2.bmp,位于包含第二个控件的命名空间。

嵌入 ToolboxItem 的位图图标

  1. 添加两个新的位图到项目,如下所示。

    1. 右击 LoadToolboxMembers 项目。

    2. 指向 添加,然后单击 新项目

    3. 添加新项目 对话框中,选择 位图文件,并将文件命名 Control1.bmp。

    4. 重复第二个位图的这些步骤并将其命名为 Control2.bmp。

      执行此操作以在 Visual Studio 位图编辑器的每个位图。

  2. 设置每个图标大小为 16 x 16,如下所示。

    1. 对于每个位图,在 视图 菜单中单击 " 属性 " 窗口

    2. 属性 窗口中,将 高度宽度 为 16。

  3. 使用位图编辑器在 Visual Studio  生成每个图标的图像。

  4. 解决方案资源管理器,单击每个位图文件,然后,在 属性 窗口中,将 生成操作 属性设置为 嵌入资源

  5. 保存所有打开的文件。

修改 VSPackage 实现

必须修改 VSPackage 的默认实现进行以下操作:

下面的过程演示如何修改包实现。

修改包实现是 VSPackage 中提供工具箱项提供程序

  1. 在代码编辑器中打开 LoadToolboxMembersPackage.cs 或 LoadToolboxMembersPackage.vb 文件。

  2. 按如下方式修改 LoadToolboxMembersPackage 类的声明,是 Package 类实现在解决方案为; 否则为。

    1. 添加以下命名空间指令。 LoadToolboxMembersPackage 类文件。

      Imports System.Collections
      Imports System.ComponentModel
      Imports System.Drawing.Design
      Imports System.Reflection
      
      using System.Collections;
      using System.ComponentModel;
      using System.Drawing.Design;
      using System.Reflection;
      
    2. 注册 VSPackage 作为 ToolboxItem 类通过添加 ProvideToolboxItemsAttribute实例。

      备注

      ProvideToolboxItemsAttribute 的唯一参数是 VSPackage 提供 ToolboxItem 的版本。更改此值强制 IDE 加载 VSPackage,即使它具有 ToolboxItem 类的早期的缓存版本。

    3. 添加下面两个新的 private 字段添加到 LoadToolboxMembersPackage 类:

      ArrayList 成员,名为 ToolboxItemList,保存 LoadToolboxMembersPackage 类管理 ToolboxItem 对象的列表。

      String,名为 CategoryTab,包含 工具箱 类别或选项用于保存 ToolboxItem 对象由 LoadToolboxMembersPackage 类管理。

    此修改的结果将类似于以下代码:

    Imports Microsoft.VisualBasic
    Imports System
    Imports System.Diagnostics
    Imports System.Globalization
    Imports System.Runtime.InteropServices
    Imports System.ComponentModel.Design
    Imports Microsoft.Win32
    Imports Microsoft.VisualStudio.Shell.Interop
    Imports Microsoft.VisualStudio.OLE.Interop
    Imports Microsoft.VisualStudio.Shell
    
    Imports System.Collections
    Imports System.ComponentModel
    Imports System.Drawing.Design
    Imports System.Reflection
    
    ' ...
    <PackageRegistration(UseManagedResourcesOnly:=True), _
    DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0"), _
    InstalledProductRegistration(False, "#110", "#112", "1.0", IconResourceID:=400), _
    ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1), _
    ProvideMenuResource(1000, 1), _
    Guid(GuidList.guidLoadToolboxMembersPkgString)> _
    <ProvideToolboxItems(1)> _
    Public NotInheritable Class LoadToolboxMembersPackage
        Inherits Package
    
        ' List for the toolbox items provided by this package. 
        Private ToolboxItemList As ArrayList
    
        ' Name for the Toolbox category tab for the package's toolbox items. 
        Private CategoryTab As String = "LoadToolboxMembers Walkthrough VB" 
    
        ' ...
    
    using System;
    using System.Diagnostics;
    using System.Globalization;
    using System.Runtime.InteropServices;
    using System.ComponentModel.Design;
    using Microsoft.Win32;
    using Microsoft.VisualStudio.Shell.Interop;
    using Microsoft.VisualStudio.OLE.Interop;
    using Microsoft.VisualStudio.Shell;
    
    using System.Collections;
    using System.ComponentModel;
    using System.Drawing.Design;
    using System.Reflection;
    
    namespace Company.LoadToolboxMembersCS
    {
        // ...
        [PackageRegistration(UseManagedResourcesOnly = true)]
        // ...
        [DefaultRegistryRoot("Software\\Microsoft\\VisualStudio\\9.0")]
        // ...
        [InstalledProductRegistration(false, "#110", "#112", "1.0", IconResourceID = 400)]
        // ...
        [ProvideLoadKey("Standard", "1.0", "Package Name", "Company", 1)]
        // ...
        [ProvideMenuResource(1000, 1)]
        [Guid(GuidList.guidLoadToolboxMembersPkgString)]
        [ProvideToolboxItems(1)]
        public sealed class LoadToolboxMembersPackage : Package
        {
            // List for the toolbox items provided by this package. 
            private ArrayList ToolboxItemList;
    
            // Name for the Toolbox category tab for the package's toolbox items. 
            private string CategoryTab = "LoadToolboxMembers Walkthrough CS";
    
            // ...
    
  3. 展开包成员区域修改 Initialize 方法进行以下操作:

    • 对于 Visual C#,请订阅 ToolboxInitializedToolboxUpgraded 事件。

    • 调用 CreateItemList 方法加载 ArrayList 对象 ToolboxItemList。 ToolboxItemList 将包含 LoadToolboxMembersPackage 管理所有工具箱项的列表。

    Protected Overrides Sub Initialize()
        Trace.WriteLine(String.Format(CultureInfo.CurrentCulture, _
            "Entering Initialize() of: {0}", Me.GetType().Name))
        MyBase.Initialize()
    
        ' Add our command handlers for menu (commands must exist in the .vsct file) 
        Dim mcs As OleMenuCommandService = _
            TryCast(GetService(GetType(IMenuCommandService)), OleMenuCommandService)
        If Not mcs Is Nothing Then 
    
            ' Create the command for the menu item. 
            Dim menuCommandID As New CommandID( _
                GuidList.guidLoadToolboxMembersCmdSet, CInt(PkgCmdIDList.cmdidMyCommand))
            Dim menuItem As New MenuCommand( _
                New EventHandler(AddressOf MenuItemCallback), menuCommandID)
            mcs.AddCommand(menuItem)
        End If 
    
        ' Use reflection to get the toolbox items provided in this assembly.
        ToolboxItemList = CreateItemList(Me.GetType().Assembly)
        If ToolboxItemList Is Nothing Then 
            ' Unable to generate the list. 
            ' Add error handling code here. 
        End If 
    End Sub
    
    protected override void Initialize()
    {
        Trace.WriteLine (string.Format(CultureInfo.CurrentCulture,
            "Entering Initialize() of: {0}", this.ToString()));
        base.Initialize();
    
        // Add our command handlers for menu (commands must exist in the .vsct file)
        OleMenuCommandService mcs =
            GetService(typeof(IMenuCommandService)) as OleMenuCommandService;
        if ( null != mcs )
        {
            // Create the command for the menu item.
            CommandID menuCommandID =
                new CommandID(GuidList.guidLoadToolboxMembersCmdSet,
                    (int)PkgCmdIDList.cmdidMyCommand);
            MenuCommand menuItem =
                new MenuCommand(MenuItemCallback, menuCommandID );
            mcs.AddCommand( menuItem );
    
            // Subscribe to the toolbox intitialized and upgraded events.
            ToolboxInitialized += new EventHandler(OnRefreshToolbox);
            ToolboxUpgraded += new EventHandler(OnRefreshToolbox);
        }
    
        // Use reflection to get the toolbox items provided in this assembly.
        ToolboxItemList = CreateItemList(this.GetType().Assembly);
        if (null == ToolboxItemList)
        {
            // Unable to generate the list. 
            // Add error handling code here.
        }
    }
    
  4. 可以使用元数据,如下所示添加两个方法, CreateItemList 和 CreateToolboxItem,若要构造,则,可在 LoadToolboxMembers 程序集 ToolboxItem 对象的实例,例如:

    ' Scan for toolbox items in the assembly and return the list of 
    ' toolbox items. 
    Private Function CreateItemList(ByVal asmbly As Assembly) As ArrayList
    
        Dim list As New ArrayList()
        For Each possibleItem As Type In asmbly.GetTypes()
    
            Dim item As ToolboxItem = CreateToolboxItem(possibleItem)
            If item IsNot Nothing Then
                list.Add(item)
            End If 
        Next 
    
        Return list
    End Function 
    
    ' If the type represents a toolbox item, return an instance of the type 
    ' otherwise, return Nothing. 
    Private Function CreateToolboxItem(ByVal possibleItem As Type) As ToolboxItem
    
        ' A toolbox item must implement IComponent and must not be abstract. 
        If Not GetType(IComponent).IsAssignableFrom(possibleItem) Or _
            possibleItem.IsAbstract Then 
    
            Return Nothing 
        End If 
    
        ' A toolbox item must have a constructor that takes a parameter of 
        ' type Type or a constructor that takes no parameters. 
        If possibleItem.GetConstructor(New Type() {GetType(Type)}) Is Nothing And _
            possibleItem.GetConstructor(New Type() {}) Is Nothing Then 
    
            Return Nothing 
        End If 
    
        Dim item As ToolboxItem = Nothing 
    
        ' Check the custom attributes of the candidate type and attempt to 
        ' create an instance of the toolbox item type. 
        Dim attribs As AttributeCollection = _
            TypeDescriptor.GetAttributes(possibleItem)
        Dim tba As ToolboxItemAttribute = TryCast( _
            attribs(GetType(ToolboxItemAttribute)), ToolboxItemAttribute)
        If tba IsNot Nothing And Not tba.Equals(ToolboxItemAttribute.None) Then 
    
            If Not tba.IsDefaultAttribute() Then 
    
                ' This type represents a custom toolbox item implementation. 
                Dim itemType As Type = tba.ToolboxItemType
                Dim ctor As ConstructorInfo = _
                    itemType.GetConstructor(New Type() {GetType(Type)})
                If ctor IsNot Nothing And itemType IsNot Nothing Then
    
                    item = CType(ctor.Invoke(New Object() {possibleItem}), ToolboxItem)
                Else
    
                    ctor = itemType.GetConstructor(New Type() {})
                    If ctor IsNot Nothing Then
    
                        item = CType(ctor.Invoke(New Object() {}), ToolboxItem)
                        item.Initialize(possibleItem)
                    End If 
                End If 
            Else 
    
                ' This type represents a default toolbox item.
                item = New ToolboxItem(possibleItem)
            End If 
    
            If item Is Nothing Then 
    
                Throw New ApplicationException("Unable to create a ToolboxItem " & _
                    "object from " & possibleItem.FullName & ".")
            End If 
        End If 
    
        ' Update the display name of the toolbox item and add the item to 
        ' the list. 
        Dim displayName As DisplayNameAttribute = TryCast( _
            attribs(GetType(DisplayNameAttribute)), DisplayNameAttribute)
        If displayName IsNot Nothing And Not displayName.IsDefaultAttribute() Then
    
            item.DisplayName = displayName.DisplayName
        End If 
    
        Return item
    End Function
    
    // Scan for toolbox items in the assembly and return the list of 
    // toolbox items. 
    private ArrayList CreateItemList(Assembly assembly)
    {
        ArrayList list = new ArrayList();
        foreach (Type possibleItem in assembly.GetTypes())
        {
            ToolboxItem item = CreateToolboxItem(possibleItem);
            if (item != null)
            {
                list.Add(item);
            }
        }
        return list;
    }
    
    // If the type represents a toolbox item, return an instance of the type; 
    // otherwise, return null. 
    private ToolboxItem CreateToolboxItem(Type possibleItem)
    {
        // A toolbox item must implement IComponent and must not be abstract. 
        if (!typeof(IComponent).IsAssignableFrom(possibleItem) ||
            possibleItem.IsAbstract)
        {
            return null;
        }
    
        // A toolbox item must have a constructor that takes a parameter of 
        // type Type or a constructor that takes no parameters. 
        if (null == possibleItem.GetConstructor(new Type[] { typeof(Type) }) &&
            null == possibleItem.GetConstructor(new Type[0]))
        {
            return null;
        }
    
        ToolboxItem item = null;
    
        // Check the custom attributes of the candidate type and attempt to 
        // create an instance of the toolbox item type.
        AttributeCollection attribs =
            TypeDescriptor.GetAttributes(possibleItem);
        ToolboxItemAttribute tba =
            attribs[typeof(ToolboxItemAttribute)] as ToolboxItemAttribute;
        if (tba != null && !tba.Equals(ToolboxItemAttribute.None))
        {
            if (!tba.IsDefaultAttribute())
            {
                // This type represents a custom toolbox item implementation.
                Type itemType = tba.ToolboxItemType;
                ConstructorInfo ctor =
                    itemType.GetConstructor(new Type[] { typeof(Type) });
                if (ctor != null && itemType != null)
                {
                    item = (ToolboxItem)ctor.Invoke(new object[] { possibleItem });
                }
                else
                {
                    ctor = itemType.GetConstructor(new Type[0]);
                    if (ctor != null)
                    {
                        item = (ToolboxItem)ctor.Invoke(new object[0]);
                        item.Initialize(possibleItem);
                    }
                }
            }
            else
            {
                // This type represents a default toolbox item.
                item = new ToolboxItem(possibleItem);
            }
        }
        if (item == null)
        {
            throw new ApplicationException("Unable to create a ToolboxItem " +
                "object from " + possibleItem.FullName + ".");
        }
    
        // Update the display name of the toolbox item and add the item to 
        // the list.
        DisplayNameAttribute displayName =
            attribs[typeof(DisplayNameAttribute)] as DisplayNameAttribute;
        if (displayName != null && !displayName.IsDefaultAttribute())
        {
            item.DisplayName = displayName.DisplayName;
        }
    
        return item;
    }
    
  5. 执行 OnRefreshToolbox 方法以处理 ToolboxInitializedToolboxUpgraded 事件。

    OnRefreshToolbox 方法使用在 LoadToolboxMembersPackage 类的 ToolboxItemList 成员包含 ToolboxItem 对象的列表。 它还进行以下操作:

    • 取消已存在工具箱类别由变量的 CategoryTab定义的所有 ToolboxItem 对象。

    • 向该类别选项的 ToolboxItemList 列表 VSProject 的所有 ToolboxItem 对象的新实例。

    • 设置 工具箱 有效的选项传递给 VSProject 的类别选项。

    Private Sub OnRefreshToolbox(ByVal sender As Object, ByVal e As EventArgs) _
        Handles Me.ToolboxInitialized, Me.ToolboxUpgraded
    
        ' Add new instances of all ToolboxItems contained in ToolboxItemList. 
        Dim service As IToolboxService = TryCast( _
                GetService(GetType(IToolboxService)), IToolboxService)
        Dim toolbox As IVsToolbox = TryCast( _
            GetService(GetType(IVsToolbox)), IVsToolbox)
    
        'Remove target tab and all controls under it. 
        For Each oldItem As ToolboxItem In service.GetToolboxItems(CategoryTab)
            service.RemoveToolboxItem(oldItem)
        Next
        toolbox.RemoveTab(CategoryTab)
    
        For Each itemFromList As ToolboxItem In ToolboxItemList
            service.AddToolboxItem(itemFromList, CategoryTab)
        Next
        service.SelectedCategory = CategoryTab
    
        service.Refresh()
    End Sub
    
    void OnRefreshToolbox(object sender, EventArgs e)
    {
        // Add new instances of all ToolboxItems contained in ToolboxItemList.
        IToolboxService service =
            GetService(typeof(IToolboxService)) as IToolboxService;
        IVsToolbox toolbox = GetService(typeof(IVsToolbox)) as IVsToolbox;
    
        //Remove target tab and all controls under it. 
        foreach (ToolboxItem oldItem in service.GetToolboxItems(CategoryTab))
        {
            service.RemoveToolboxItem(oldItem);
        }
        toolbox.RemoveTab(CategoryTab);
    
        foreach (ToolboxItem itemFromList in ToolboxItemList)
        {
            service.AddToolboxItem(itemFromList, CategoryTab);
        }
        service.SelectedCategory = CategoryTab;
    
        service.Refresh();
    }
    

    备注

    作为练习,一个可以开发测试的 VSPackage 或项目的版本一个框架和只更新,如果 VSPackage 的版本的更改,或者,如果 ToolboxItem 的版本的更改。

初始化工具箱

实现命令初始化工具箱

  • 将菜单项命令处理程序方法, MenuItemCallBack,如下所示。

    1. 用下面的代码替换 MenuItemCallBack 的现有实现:

      Private Sub MenuItemCallback(ByVal sender As Object, ByVal e As EventArgs)
          Dim pkg As IVsPackage = TryCast(GetService(GetType(Package)), Package)
          pkg.ResetDefaults(CUInt(__VSPKGRESETFLAGS.PKGRF_TOOLBOXITEMS))
      End Sub
      
      private void MenuItemCallback(object sender, EventArgs e)
      {
          IVsPackage pkg = GetService(typeof(Package)) as Package;
          pkg.ResetDefaults((uint)__VSPKGRESETFLAGS.PKGRF_TOOLBOXITEMS);
      }
      

生成并运行解决方案

可以执行本演练产品通过在的实验项运行 Visual Studio 的实例。

执行本演练

  1. 在 Visual Studio 中,在 生成 菜单上,单击 重新生成解决方案

  2. 按 F5 开始 Visual Studio 第二个实例在的实验注册表项。

    有关如何使用测试项的更多信息,请参见 Visual Studio 的实验实例

  3. 单击**“工具”**菜单。

    命令名为 初始化 LoadToolboxMembers VB初始化 LoadToolboxMembers cs 应出现在菜单顶部,与数字 1. 的图标。

  4. 创建新的 Visual C# 或 Visual Basic windows 窗体应用程序。

    Form基于设计器应显示。

  5. 新的控件之一或两者在 工具箱LoadToolboxMembers 演练 VBLoadToolboxMembers 演练 cs 类别的于窗体的设计器中。

    备注

    如果 工具箱 未显示,请单击 工具箱视图 菜单。如果 VSPackage 的类别选项不会出现在 工具箱,通过单击 初始化 LoadToolboxMembers VB初始化 LoadToolboxMembers cs 重新初始化 工具箱工具 菜单。

  6. 通过单击 重新生成解决方案 生成 windows 应用程序在 生成 菜单。

  7. 应用程序通过单击 开始从开始调试 从开始调试调试 菜单。

  8. 在应用程序运行时,单击您添加到应用程序的一个控件。

    消息框将出现并显示 "Hello world from Company.LoadToolboxMembers.Control1" 或"Hello world from Company.LoadToolboxMembers.Control2"。

对于实现的分析

创建工具箱控件

,该查询可用 工具箱 控件时, Assembly 分配给 Control1 和 Control2 方法使用属性 CreateItemList 。

  • ToolboxItemAttribute 执行以下两个功能:

  • ToolboxBitmapAttribute 类指定环境用于标识控件的位图。

    位图嵌入在一个程序集通过设置为 嵌入资源生成操作 属性程序集中的命名空间将位图。 因此, Control1.bmp 可以引用 Company.LoadToolboxMembers.Control1.bmp。

    ToolboxBitmapAttribute 支持上此完整路径作为参数的构造函数。 例如,通过使用 [ToolboxBitmap("Company.LoadToolboxMembers.Control1.bmp")], ToolboxBitmapAttribute 类可以应用于 Control1 。

    若要支持灵活性,本演练使用上 Type 型类作为第一个参数。 ToolboxBitmapAttribute 构造函数的构造函数。 用于标识位图文件的命名空间从 Type 获取并在位图前面的基名称插入。

    由于 Type 对象实现 Package, LoadToolboxMembers,在 Company.LoadToolboxMembers 命名空间 [ToolboxBitmap(typeof(Control1), "Control1.bmp")] 与 [ToolboxBitmap("Company.LoadToolboxMembers.Control1.bmp")]等效。

  • DisplayNameAttribute工具箱指定控件名称。

注册工具箱控件提供程序

应用 ProvideToolboxItemsAttribute 类中实现 Package 影响生成的 VSPackage 的注册表设置的类。 有关 ToolboxItem 提供程序的注册表设置的更多信息,请参见 注册工具箱支持功能

Visual Studio 环境使用版本参数传递给构造函数 ProvideToolboxItemsAttribute 管理提供项目。 工具箱Vspackage 的缓存。 在 VSPackage 加载提供 工具箱 项目后,使用 VSPackage 中缓存的版本,直到该提供程序的注册表的版本更改。 因此,因此,如果要修改此演练产品,可以在编译之后,请确保更改会应用于 AddToolboxItemProvideToolboxItemsAttribute 构造函数的版本参数。 例如,应更改 [ProvideToolboxItems(1)] 到 [ProvideToolboxItems(2)]。 如果未更改版本,则 Visual Studio 环境不加载做的所有修改。

在本演练中,配置 VSPackage 提供支持默认剪贴板格式的仅 工具箱 控件。 有关默认剪贴板格式列表,请参见 工具箱 (Visual Studio SDK)。 如果希望支持其他剪贴板格式或确定不支持默认布局,将特性 ProvideToolboxFormatAttribute 于 LoadToolboxMembersPackage 类。 有关注册 工具箱 的更多信息的控件提供程序,请参见 高级工具箱控件开发

将控件添加到工具箱

在 CreateItemList 的函数模拟可在 System#Drawing#Design#IToolboxService#GetToolboxItems

CreateItemList 方法只检查实现 IComponent 接口的非抽象 Type 对象。

后续步骤

使用 System#Drawing#Design#IToolboxService#GetToolboxItems 而不是 CreateItemList 使该产品本演练更加可靠。

您还可以更改 CreateItemList 使用 ParseToolboxResource 到加载控件根据在 LoadToolboxMembers 程序集中嵌入文本的 工具箱 列表。

请参见

任务

高级工具箱控件开发

概念

注册工具箱支持功能

其他资源

工具箱 (Visual Studio SDK)

工具箱演练