How to: Create an Editor for a VSPackage
The following steps outline the process for creating a standard editor for a VSPackage.
Notes
Beginning with Visual Studio 2008 SDK, use XML Command Table (.vsct) files instead of command table configuration (.ctc) files to define how menus and commands appear in your VSPackages. For more information, see XML-Based Command Table Configuration (.vsct) Files.
To create an editor for a VSPackage
Create a VSPackage that the integrated development environment (IDE) loads to instantiate your editor.
For more information, see How to: Create VSPackages (C# and VB).
Decide whether you want your editor to support a single view or multiple views.
An editor that supports the New Window command, or has form view and code view, requires separate document data objects and document view objects. In an editor that supports only a single view, the document data object and the document view object can be implemented on the same object.
For an example of multiple views, see Supporting Multiple Document Views and the Figures Edit sample. For an example of a single view, see the Basic Edit sample.
Implement an editor factory by implementing the IVsEditorFactory interface.
For more information, see Editor Factories.
Decide whether you want your editor to use in-place activation or simplified embedding to manage the document view object window.
A simplified embedding editor window hosts a standard document view, while an in-place activation editor window hosts an ActiveX control or other active object as its document view. Both the simplified embedding and in-place activation approaches are demonstrated in the Basic Edit sample. For more information, see Simplified Embedding and In-Place Activation.
Implement the IOleCommandTarget interface to handle commands.
Provide document persistence and response to external file changes by doing the following:
To persist the file, implement IVsPersistDocData2 and IPersistFileFormat on your editor's document data object.
To respond to external file changes, implement IVsFileChangeEx and IVsDocDataFileChangeControl on your editor's document data object.
Notes
Call QueryService on SVsFileChangeEx to obtain a pointer to IVsFileChangeEx.
Coordinate document edit events with source code control. To do this:
Obtain a pointer to IVsQueryEditQuerySave2 by calling QueryService on SVsQueryEditQuerySave.
When the first edit event occurs, call the QueryEditFiles method.
This prompts the user to check out the file if it is not already checked out. Be sure to handle a "file not checked out" condition to avert errors
Similarly, before saving the file, call the QuerySaveFile method.
This method prompts the user to save the file if it has not been saved or if it has changed since the last save.
Enable the Properties window to display properties for text selected in the editor. To do this:
Call OnSelectChange each time text selection changes, passing in your implementation of ISelectionContainer.
Call QueryService on STrackSelection service to obtain a pointer to ITrackSelection.
For more information, see How to: Announce Selection Tracking to the Environment.
Enable users to drag and drop items between the editor and the Toolbox, or between external editors (like Microsoft Word) and the Toolbox. To do this:
Implement IDropTarget on your editor to alert the IDE that your editor is a drop target.
Implement the IVsToolboxUser interface on the view so your editor can enable and disable items in the Toolbox.
Implement ResetDefaults and call QueryService on SVsToolbox service to obtain a pointer to the IVsToolbox2 and IVsToolbox3 interfaces.
This enables your VSPackage to add new items to the Toolbox.
For more information, see the Figures Edit sample and How to: Support Toolbox Drag-and-Drop Functionality.
Decide whether you want any other optional features for your editor.
If you want your editor to support find and replace commands, implement IVsFindTarget. For more information, see the Basic Edit sample.
If you want your editor to support macro recording, call QueryService for SVsMacroRecorder to obtain a pointer to IVsMacroRecorder.
Notes
The IDE supports macro recording when the editor supports it. For an example of using IVsMacroRecorder, see the Basic Edit sample.
If you want to use a document outline tool window in your editor, implement IVsDocOutlineProvider.
For an example of how to use a document outline window, see the Figures Edit sample.
If you want to use a status bar in your editor, implement IVsStatusbarUser and call QueryService for SVsStatusbar to obtain a pointer to IVsStatusBar.
For example, an editor can display line / column information, selection mode (stream / box), and insertion mode (insert / overstrike). For more information, see the Basic Edit sample and How to: Update the Status Bar.
If you want your editor to support the Undo command, the recommended method is to use the OLE undo manager model. As an alternative, you can have the editor handle the Undo command directly.
For more information, see How to: Implement Undo Management.
Create registry Information, including the GUIDs for the VSPackage, the menus, the editor, and other features.
The following is a generic example of code that you would put in your .rgs file script to demonstrate how to properly register an editor.
NoRemove Editors { ForceRemove {...guidEditor...} = s 'RTF Editor' { val Package = s '{...guidVsPackage...}' ForceRemove Extensions { val rtf = d 50 } } } NoRemove Menus { val {...guidVsPackage...} = s ',203,11' }
Implement context-sensitive Help support.
This allows you to provide F1 Help and Dynamic Help window support for items in your editor. For more information on this, see How to: Provide Context for Editors or Designers.
Expose an Automation Object Model from your editor by implementing the IDispatch interface.
For more information, see the Basic Edit sample and Contributing to the Automation Model.
Robust Programming
The editor instance is created when the IDE calls the CreateEditorInstance method. If the editor supports multiple views, CreateEditorInstance creates both the document data and the document view objects. If the document data object is already open, a non-null punkDocDataExisting value is passed to IVsEditorFactory::CreateEditorInstance. Your editor factory implementation must determine whether an existing document data object is compatible by querying for appropriate interfaces on it. For more information, see Supporting Multiple Document Views.
If you use the simplified embedding approach, implement the IVsWindowPane interface.
If you decide to use in-place activation, implement the following interfaces:
Notes
The IOleInPlaceComponent interface is used to avoid OLE 2 menu merging.
Your IOleCommandTarget implementation handles commands such as Cut, Copy, and Paste. When implementing IOleCommandTarget, decide whether your editor requires its own .ctc file to define its own command menu structure or if it can implement standard commands defined by Visual Studio. Typically, editors use and extend the IDE's menus and define their own toolbars. However, it often is necessary for an editor to define its own specific commands in addition to using the IDE's standard command set. To do this, your editor must declare the standard commands it uses and then define any new commands, context menus, top-level menus and toolbars in a .ctc file. If you create an in-place activation editor, then implement IOleInPlaceComponent and define the menus and toolbars for the editor in a .ctc file instead of using OLE 2 menu merging. The use of .ctc files is demonstrated in the Basic Edit sample and discussed in Command Table Configuration (.Ctc) Files.
To prevent menu command crowding in the UI, you should use the existing commands in the IDE before inventing new commands. Standard commands are defined in stdcmdid.h. CTC information for shared commands is defined in SharedCmdDef.ctc and ShellCmdDef.ctc. These files are installed by default in the VisualStudioIntegration\Common\Inc subdirectory of your Visual Studio SDK installation.
ISelectionContainer can express both single and multiple selections. Each selected object is implemented as an IDispatch object.
The IDE implements IOleUndoManager as a service accessible from a CreateInstance or as an object that can be instantiated through CreateInstance. Your editor implements the IOleUndoUnit interface for each Undo action.
There are two places a custom editor can expose automation objects:
Document.Object
Window.Object