How do I implement a custom Text marker?
A: Aha! Custom text markers are one of those cool features lacking adequate documentation on how to implement it. I feel that implementing one is really very straight forward and hope you would be able to use to your heart's content.
Providing custom markers text markers essentially boils down to implementing three components
· A text marker service that proffers the service. Implements IVsTextMarkerTypeProvider
· The custom text marker. Implements IVsPackageDefinedTextMarkerType and IVsMergeableUIItem.
· And optionally a call back object so shell can call to notify of some events that implements IVsTextMarkerClient
Implementing Text Marker Service
Implementation of IVsTextMarkerTypeProvider essentially allows you to proffer your marker service and returns an instance of your marker when requested. The marker is usuallly identified by a MarkerId(DWORD). This value can be obtained from the text manager. You should do this typically when you create a marker instance returned by IVsTextMarkerTypeProvider::GetTextMarkerType
Obtaining the marker ID |
CComPtr<IVsTextManager> pTextMgr = _Module.GetIVsTextManager(); pTextMgr->GetRegisteredMarkerTypeID(&guidCodeMarker, &m_markerID); pTextMgr.Release(); |
Implementing the marker service |
STDMETHODIMP CAnnotationTextMarkerSvc::GetTextMarkerType( GUID* pguidMarker, IVsPackageDefinedTextMarkerType** ppMarkerType) { if(*pguidMarker == guidCodeMarker) return <your_marker_type> return E_FAIL; } |
Proffer the Code marker service |
CComPtr<IProfferService> srpProffer; DWORD dwCookie; if((SUCCEEDED(_Module.QueryService(SID_SProfferService, IID_IProfferService, (void **)&srpProffer))) && (srpProffer != NULL)) { srpProffer->ProfferService(<<guidMyMarkerService>>, (IServiceProvider *) this, &dwCookie); } |
Implementing the TextMarker
IVsPackageDefinedTextMarkerType and IVsMergeableUIItem are the two interfaces required to be implemented by a custom Text marker
IVsPackageDefinedTextMarkerType - This is implemented to determine marker information applicable to your custom marker type. This provides information ranging from default fonts and colors to actually doing the drawing of the glyph. This object is what specifies what the marker type should be and where the marker glyph should show up.
Couple of rules that you need to comply with when implementing
IVsPackageDefinedMarkerType::DrawGlyphWithColors
· Do not draw anything outside of the passed RECT
· Because the size of line can change on the fly use GDI primitives rather than bitmaps as they won’t scale well with size changes
· Do not draw any text.
IVsMergeableUIItem - This is needed to have your marker participate in the Environment->Fonts and Colors Options page so you can take full advantage of all the font and color options. Essentially you get the font and color support for free.
The priority value returned by the IVsMergeableUIItem::GetMergingPriority is used to decide what name to show for the marker when two markers are found with the same canonical name. For non- Microsoft component the priority should be between 0 and 0x1000. If you are not doing any localization this value should be negative.
You create an instance of the marker object and return it to the shell via: IVsTextMarkerTypeProvider::GetTextMarkerType
Getting called back:
If you interested in being informed of changes to an individual marker then implement IVsTextMarkerClient. For e.g if you want to send back tooltips or put up special context menu items for your marker. You would hand this object to the shell when you make a call to IVsTextLines::CreateLineMarker.
Create a text marker client that will be called back |
CComObject<CAnnotationTextMarkerClient>* pTMClient; CComObject<CAnnotationTextMarkerClient>::CreateInstance(&pTMClient); |
Create the marker |
IfFailGo(pLines->CreateLineMarker ( m_markerID, line, // starting line 0, // starting character index within the line (must be <= length of line) line, // ending line len, // ending character index within the line (must be <= length of line) pTMClient, // client object for call backs NULL)); |
Registration:
Here is what you need to register for the text marker and related service.
Registration script |
NoRemove 'Text Editor' { NoRemove 'External Markers' { ForceRemove '{<YOUR_MARKER_TYPE_GUID>}' = s 'My Sample Text Marker' { val Service = s '{<YOUR_MARKER_SERVICE_GUID>}' val DisplayName = s 'My Sample Text Marker' val Package = s '{<PACKAGE_GUID>}' } } } NoRemove Services { ForceRemove '{<YOUR_MARKER_SERVICE_GUID>}' = s '%<PACKAGE_GUID>e%' { val Name = s 'My Sample Text Marker Service' } } |
Thanks
Dr. eX
Comments
Anonymous
June 13, 2004
Hi,
I've implemented custom text markers just as you recommend, and all works fine except for one subtle issue:
my custom text markers seem to have bad influence on debugger markers (such as
breakpoints &
current statement pointer). The symptom is that debugger markers often
retain even after actions
that should remove them. For example, when I click on the left gutter to
remove a breakpoint,
breakpoint is indeed removed (as can be seen from
Debug->Windows->Breakpoints window) but the corresponding
text marker still presents in the text. It gets removed after some UI events
like mouse wheeling, moving the caret etc -
so far I've failed to figure out exactly which events cause deletion of the
debugger marker. The same situation is observed
with the current statement pointer. Both issues don't reproduce always, but
in a permanent manner, and really disturb
users.
If you could provide an insight on this problem, it would be really great.
Thanks,
DmitryAnonymous
July 08, 2004
I've been working on a demo editor package that implements custom markers, but haven't seen this particular behavior.
The BP tooltip doesn't get dismissed when you click on the BP to remove it. You can see this behavior with just the generic code editor.
You see this same behavior if you create a custom marker on top of a BP marker. But I'm not sure if this is the behavior you're referring to.Anonymous
September 10, 2008
PingBack from http://www.fillinger.net/?p=18Anonymous
January 21, 2009
PingBack from http://www.keyongtech.com/2399305-syntax-highlighting-for-net-addin