演练:向自定义编辑器添加功能

创建自定义编辑器后,可以向其添加更多功能。

为 VSPackage 创建编辑器

  1. 使用 Visual Studio 包项目模板创建自定义编辑器。

    有关详细信息,请参阅 演练:创建自定义编辑器

  2. 确定是否希望编辑器支持单个视图或多个视图。

    支持 “新建窗口” 命令或具有窗体视图和代码视图的编辑器需要单独的文档数据对象和文档视图对象。 在仅支持单个视图的编辑器中,文档数据对象和文档视图对象可以在同一对象上实现。

    有关多个视图的示例,请参阅 “支持多个文档视图”。

  3. 通过设置 IVsEditorFactory 接口来实现编辑器工厂。

    有关详细信息,请参阅 编辑器工厂

  4. 确定是希望编辑器使用就地激活还是简化嵌入来管理文档视图对象窗口。

    简化的嵌入编辑器窗口托管标准文档视图,而就地激活编辑器窗口承载 ActiveX 控件或其他活动对象作为其文档视图。 有关详细信息,请参阅 简化的 嵌入和 就地激活

  5. IOleCommandTarget实现用于处理命令的接口。

  6. 提供对外部文件更改的文档持久性和响应:

    1. 若要保存文件,请在编辑器的文档数据对象上实现 IVsPersistDocData2IPersistFileFormat 实现。

    2. 若要响应外部文件更改,请在编辑器的文档数据对象上实现 IVsFileChangeExIVsDocDataFileChangeControl 处理。

      注意

      SVsFileChangeEx调用QueryService以获取指向IVsFileChangeEx的指针。

  7. 使用源代码控制协调文档编辑事件。 请遵循以下步骤:

    1. 通过调用QueryServiceSVsQueryEditQuerySave获取指向IVsQueryEditQuerySave2的指针。

    2. 发生第一个编辑事件时,调用 QueryEditFiles 该方法。

      此方法提示用户检查文件(如果尚未检查出)。请务必处理“文件未检查退出”条件来避免错误。

    3. 同样,在保存文件之前,请调用 QuerySaveFile 该方法。

      此方法提示用户保存文件(如果文件尚未保存或自上次保存以来已更改)。

  8. 启用“属性”窗口以显示编辑器中选择的文本的属性。 执行以下步骤:

    1. 每次文本选择更改时调用OnSelectChange,传入实现。ISelectionContainer

    2. STrackSelection调用QueryService服务以获取指向ITrackSelection的指针。

  9. 允许用户在编辑器和工具箱之间或外部编辑器(如 Microsoft Word)和工具箱之间拖放项。 执行以下步骤:

    1. 在编辑器上实现 IDropTarget ,以提醒 IDE 编辑器是放置目标。

    2. IVsToolboxUser视图上实现接口,以便编辑器可以在工具箱启用和禁用项。

    3. 实现ResetDefaults并调用QueryServiceSVsToolbox服务以获取指向和IVsToolbox3接口的IVsToolbox2指针。

      这些步骤使 VSPackage 能够向工具箱添加新项

  10. 确定是否要为编辑器提供任何其他可选功能。

    • 如果希望编辑器支持查找和替换命令,请实现 IVsFindTarget

    • 如果要在编辑器中使用文档大纲工具窗口,请实现 IVsDocOutlineProvider

    • 如果要在编辑器中使用状态栏,请实现IVsStatusbarUser并调用QueryServiceSVsStatusbar以获取指向IVsStatusBar的指针。

      例如,编辑器可以显示行/列信息、选择模式(流/框)和插入模式(插入/超线)。

    • 如果希望编辑器支持该 Undo 命令,建议的方法是使用 OLE 撤消管理器模型。 或者,你可以让编辑器直接处理 Undo 命令。

  11. 创建注册表信息,包括 VSPackage 的 GUID、菜单、编辑器和其他功能。

    下面是一个将放入 .rgs 文件脚本的代码的一般示例,演示如何正确注册编辑器。

    NoRemove Editors
    {
          ForceRemove {...guidEditor...} = s 'RTF Editor'
          {
             val Package = s '{...guidVsPackage...}'
             ForceRemove Extensions
             {
                val rtf = d 50
             }
          }
    }
    NoRemove Menus
    {
          val {...guidVsPackage...} = s ',203,11'
    }
    
  12. 实现上下文相关的帮助支持。

    此步骤允许你为编辑器中的项提供 F1 帮助和动态帮助窗口支持。 有关详细信息,请参阅 “如何:为编辑器提供上下文”。

  13. 通过实现 IDispatch 接口,从编辑器公开自动化对象模型。

    有关详细信息,请参阅 自动化模型概述

可靠编程

  • IDE 调用 CreateEditorInstance 该方法时会创建编辑器实例。 如果编辑器支持多个视图, CreateEditorInstance 则同时创建文档数据和文档视图对象。 如果文档数据对象已打开,则传递给IVsEditorFactory::CreateEditorInstance非 null punkDocDataExisting 值。 编辑器工厂实现必须通过查询相应的接口来确定现有文档数据对象是否兼容。 有关详细信息,请参阅 支持多个文档视图

  • 如果使用简化的嵌入方法,请实现 IVsWindowPane 接口。

  • 如果决定使用就地激活,请实现以下接口:

    IOleObject

    IOleInPlaceActiveObject

    IOleInPlaceComponent

    注意

    IOleInPlaceComponent 接口用于避免 OLE 2 菜单合并。

    实现IOleCommandTarget处理剪切、复制粘贴命令。 实现 IOleCommandTarget时,确定编辑器是否需要自己的 .vsct 文件来定义自己的命令菜单结构,或者是否可以实现 Visual Studio 定义的标准命令。 通常,编辑器使用和扩展 IDE 的菜单并定义其自己的工具栏。 但是,除了使用 IDE 的标准命令集外,编辑器通常还需要定义自己的特定命令。 编辑器必须声明它使用的标准命令,然后定义 .vsct 文件中的任何新命令、上下文菜单、顶级菜单和工具栏。 如果创建就地激活编辑器,请在 .vsct 文件中实现IOleInPlaceComponent和定义编辑器的菜单和工具栏,而不是使用 OLE 2 菜单合并。

  • 若要防止 UI 中的菜单命令拥挤,应在发明新命令之前使用 IDE 中的现有命令。 共享命令在 SharedCmdDef.vsctShellCmdDef.vsct定义。 这些文件默认安装在 Visual Studio SDK 安装的 VisualStudioIntegration\Common\Inc 子目录中。

  • ISelectionContainer 可以表达单个和多个选择。 每个选定的对象都作为对象 IDispatch 实现。

  • IDE 实现 IOleUndoManager 为可从 CreateInstance 可通过实例化 CreateInstance的对象访问的服务。 编辑器为每个Undo操作实现IOleUndoUnit接口。

  • 自定义编辑器可以公开自动化对象有两个位置:

    • Document.Object

    • Window.Object