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,
    Dmitry

  • Anonymous
    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=18

  • Anonymous
    January 21, 2009
    PingBack from http://www.keyongtech.com/2399305-syntax-highlighting-for-net-addin