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