Udostępnij za pośrednictwem


New or Changed Behavior with Editor Adapters

Note

This article applies to Visual Studio 2015. If you're looking for the latest Visual Studio documentation, see Visual Studio documentation. We recommend upgrading to the latest version of Visual Studio. Download it here

If you are updating code that was written against earlier versions of the Visual Studio core editor, and you plan to use the editor adapters (or shims) rather than using the new API, you should be aware of the following differences in the behavior of the editor adapters with respect to the previous core editor.

Features

Using SetSite()

You must call SetSite when you CoCreate text buffers, text views, and code windows before you perform any other operations on them. However, this is not necessary if you use the IVsEditorAdaptersFactoryService to create them, because this service's Create() methods themselves call SetSite.

Hosting IVsCodeWindow and IVsTextView in your own content

You can host both IVsCodeWindow and IVsTextView in your own content using either Win32 mode or WPF mode. However, you should keep in mind that there are some differences in the two modes.

Using Win32 and WPF versions of IVsCodeWindow

The editor code window is derived from WindowPane, which implements the older Win32 IVsWindowPane interface as well as the new WPF IVsUIElementPane interface. You can use the IVsWindowPane.CreatePaneWindow method to create an HWND-based hosting environment, or the IVsUIElementPane.CreateUIElementPane method to create a WPF hosting environment. The underlying editor always uses WPF, but you can create the kind of window pane that suits your hosting requirements if you are embedding this window pane directly into your own content.

Using Win32 and WPF versions of IVsTextView

You can set an IVsTextView to Win32 mode or WPF mode.

When an editor factory creates a text view, by default it is hosted inside an HWND, and GetWindowHandle returns an HWND. You should not use this mode to embed the editor inside a WPF control.

To set a text view to WPF mode, you must call Initialize and pass in TextViewInitFlags3 as one of the initialization flags in the InitView parameter. You can get the FrameworkElement by calling CreateUIElementPane.

WPF mode differs from Win32 mode in two ways. First, the text view can be hosted in a WPF context. You can access the WPF pane by casting the IVsTextView to IVsUIElementPane and calling GetUIObject. Second, GetWindowHandle still returns an HWND, but this HWND can be used only to check its position and set focus on it. You must not use this HWND to respond to a WM_PAINT message, because it will not affect how the editor paints the window. This HWND is present only to facilitate the transition to the new editor code by means of the adapters. It is highly recommended that you should not use VIF_NO_HWND_SUPPORT if your component requires an HWND to work, due to the limitations in the HWND returned from GetWindowHandle while in this mode.

Passing arrays as parameters in native code

There are many methods in the legacy editor API that have parameters that include an array and its count. Examples are:

AppendViewOnlyMarkerTypes

RemoveViewOnlyMarkerTypes

If you are calling these methods in native code, you must pass in only one element at a time. If you pass in more than one element, the call will be rejected, due to problems with the primary interop implementation.

The problem is more complex with methods such as SetIgnoreMarkerTypes. Every time this method is called, it clears the previous list of ignored marker types, so it is not possible simply to call this method three times with three different marker types. The only remedy is to call this method only in managed code.

Threading

You should always call the buffer adapter from the UI thread. The buffer adapter is a managed object, which means that calling into it from managed code will bypass COM marshaling and your call will not automatically be marshaled to the UI thread. If you are calling the buffer adapter from a background thread, you must use Invoke or a similar method.

LockBuffer methods

All LockBuffer() methods are deprecated. Examples are:

LockBuffer

LockBuffer

LockBuffer

Commit events

Commit events are not supported. Calling a method that advises for these events causes the method to return a failure code.

IVsPreliminaryTextChangeCommitEvents

IVsFinalTextChangeCommitEvents

IVsUndoRedoClusterWithCommitEvents

TextEditorEvents

The TextEditorEvents no longer fire on Commit(). Instead they fire on every text change.

Text Markers

You must call Invalidate on IVsTextMarker objects when you remove them. In previous versions, you needed only to release the markers.

Line numbers

For a variety of methods on IVsTextView and IVsTextViewEx, line numbers correspond to underlying buffer line numbers, not line numbers that factor in outlining and word-wrap, as in Visual Studio 2008.

The methods affected include the following (the list is not exhaustive):

Outlining

Clients of IVsHiddenTextSession will see only those outlining regions that were added using AddHiddenRegionsor AddHiddenRegionsEx. They will not see ad hoc regions, because they are not added through the editor adapters. Likewise, these clients will not see outlining regions added by languages (including C# and C++) that are using the new editor code rather than the editor adapters.

Line heights

In the new editor, text lines can have different heights, depending on the font size and possible line transforms that may move the line relative to other lines. The line height returned by methods such as GetLineHeight is the height of a line using the default font size with no line transforms applied. This height may or may not reflect the actual height of a line in the view.

Eventing and undo

In the new editor, the view continues to perform operations such as rendering and raising events continuously, even when an undo cluster is open. This behavior is different from that of legacy views, which did not perform those operations until after the closing of the undo cluster.

IntelliSense

SmartTags

There is no adapter support for smart tags created with, IVsSmartTagData, IVsSmartTagTipWindow, and IVsSmartTagTipWindow2 interfaces.

DTE

IncrementalSearch is not implemented.

Unimplemented methods

Some methods have not been implemented on the text buffer adapter, text view adapter, and text layer adapter.

Interface Not implemented
IVsTextBuffer Reload(false) is not implemented.
IVsTextBufferCoordinator EnumSpans

SetBufferMappingModes

SetSpanMappings
IVsTextLines GetMarkerData

ReleaseMarkerData
IVsTextLayer CanReplaceLines

CopyLineText

CreateTrackingPoint

EnumLayerMarkers

GetBaseBuffer

GetLengthOfLine

GetLineCount

GetLineText

GetMarkerData

LockBufferEx

MapLocalSpansToTextOriginatingLayer

ReleaseMarkerData

ReplaceLines

ReplaceLinesEx

UnlockBufferEx
IVsFindTarget Find

Replace
IVsLayeredTextView GetSelectedAtom
IVsTextView GetSelectionDataObject

PositionCaretForEditing

RestrictViewRange

UpdateViewFrameCaption
IVsTextViewEx GetSmartTagRect

InvokeInsertionUI

SetHoverWaitTimer
IVsCodeWindow SetViewClassID
IVsIntellisenseHost AfterCompletorCommit

BeforeCompletorCommit

Exec

GetContextLocation

GetServiceProvider

GetSmartTagRect

GetSubjectCaretPos

GetSubjectSelection

GetSubjectText

QueryStatus

ReplaceSubjectTextSpan

SetSubjectCaretPos

SetSubjectSelection

UpdateSmartTagWindow
IVsTextViewIntellisenseHost SetSubjectFromPrimaryBuffer is implemented in the adapters but ignored by the outlining UI.
IVsHiddenRegionEx GetBannerAttr is implemented in the adapters but ignored by the outlining UI.