Hello,
I need to make a specific text marker in pre-VS2010 IDEs.
I am working on VS feature that provides some language specific selections
and I need to preview a result in text editor without using of a real selection.
Possibly with color that user can define/modify in options.
So I decided to implement custom text line marker as follows:
class MyMarkerType : public IVsPackageDefinedTextMarkerType, public IVsMergeableUIItem, public IVsHiColorItem { ... };source:
// IUnknown HRESULT STDMETHODCALLTYPE MyMarkerType::QueryInterface(/* [in] */ REFIID riid, /* [iid_is][out] */ void **ppvObject) { if (riid == IID_IUnknown || riid == IID_IVsPackageDefinedTextMarkerType) { *ppvObject = this; AddRef(); return S_OK; } else if (riid == IID_IVsMergeableUIItem) { *ppvObject = static_cast<IVsMergeableUIItem*>(this); AddRef(); return S_OK; } else if (riid == IID_IVsHiColorItem) { *ppvObject = static_cast<IVsHiColorItem*>(this); AddRef(); return S_OK; } *ppvObject = NULL; return E_NOINTERFACE; } ULONG STDMETHODCALLTYPE MyMarkerType::AddRef() { return InterlockedIncrement(&mRefCount); } ULONG STDMETHODCALLTYPE MyMarkerType::Release() { const LONG cRef = InterlockedDecrement(&mRefCount); if (cRef == 0) delete this; return cRef; } // IVsPackageDefinedTextMarkerType HRESULT STDMETHODCALLTYPE MyMarkerType::GetVisualStyle(/* [out] */ DWORD *pdwVisualFlags) { *pdwVisualFlags = MV_BORDER | MV_COLOR_ALWAYS; return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetDefaultColors(/* [out] */ COLORINDEX *piForeground, /* [out] */ COLORINDEX *piBackground) { *piBackground = CI_SYSSEL_BK; *piForeground = CI_SYSSEL_FG; return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetDefaultLineStyle(/* [out] */ COLORINDEX *piLineColor, /* [out] */ LINESTYLE *piLineIndex) { *piLineIndex = LI_SOLID; *piLineColor = CI_BLACK; return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetDefaultFontFlags(/* [out] */ DWORD *pdwFontFlags) { *pdwFontFlags = FF_DEFAULT; return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::DrawGlyphWithColors(/* [in] */ HDC /*hdc*/, /* [in] */ RECT * /*pRect*/, /* [in] */ long /*iMarkerType*/, /* [in] */ IVsTextMarkerColorSet * /*pMarkerColors*/, /* [in] */ DWORD /*dwGlyphDrawFlags*/, /* [in] */ long /*iLineHeight*/) { return E_NOTIMPL; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetBehaviorFlags(/* [out] */ DWORD *pdwFlags) { *pdwFlags = MB_DEFAULT; return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetPriorityIndex(/* [out] */ long *piPriorityIndex) { *piPriorityIndex = 751; // one higher than the Brace Marker return S_OK; } // IVsMergeableUIItem HRESULT STDMETHODCALLTYPE MyMarkerType::GetCanonicalName(/* [out] */ BSTR *pbstrNonLocalizeName) { CComBSTR name(L"My marker"); *pbstrNonLocalizeName = name.Detach(); return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetDescription(/* [out] */ BSTR *pbstrDesc) { CComBSTR desc(L"My marker"); *pbstrDesc = desc.Detach(); return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetDisplayName(/* [out] */ BSTR *pbstrDisplayName) { CComBSTR name(L"VMy marker"); *pbstrDisplayName = name.Detach(); return S_OK; } HRESULT STDMETHODCALLTYPE MyMarkerType::GetMergingPriority(/* [out] */ long *piMergingPriority) { *piMergingPriority = 0x2001; return S_OK; } //IVsHiColorItem HRESULT STDMETHODCALLTYPE MyMarkerType::GetColorData(/* [in] */ VSCOLORDATA cdElement, /* [out] */ COLORREF *pcrColor) { HRESULT retval = E_NOTIMPL; *pcrColor = 0; // Indicates that the returned RGB value is an index into a predefined list of colors. // http://msdn.microsoft.com/sk-sk/library/microsoft.visualstudio.textmanager.interop.ivshicoloritem.aspx const UINT COLOR_INDEXED = 0x01000000; // Once we could want to use different colors, // so this method may become handy switch (cdElement) { case CD_BACKGROUND: //*pcrColor = COLOR_INDEXED | CI_SYSSEL_BK; *pcrColor = ::GetSysColor(COLOR_HIGHLIGHT); retval = S_OK; break; case CD_FOREGROUND: case CD_LINECOLOR: //*pcrColor = COLOR_INDEXED | CI_SYSSEL_FG; *pcrColor = ::GetSysColor(COLOR_HIGHLIGHTTEXT); retval = S_OK; break; default: retval = E_INVALIDARG; break; } return retval; }
However I am getting unwanted results.
What I get:
What I want:
As you can see, on picture labeled "What I get", marker selects whole lines.
I tried also to create a unique line marker for each line, but result was same
when span contained also linebreak. If span did not contain linebreak, markes
seem good, however marker w/o linebreaks is unwanted in this case.
All markers were created using IVsTextLines::CreateLineMarker method.
Any suggestion to have markers as on picture "What I want"?
Thanks in advance,
Dusan