You are my only hope. I have searched everywhere and just can't find anything that could help me with this one.
I've done a simple code marking plugin for Visual Studio (2010). It just finds some parts of code to highlight (by Regex), creates Spans out of the matches found and then creates Rectangle adornments for them (in the background of the text), that scroll with the text. All of this is done in view.LayoutChanged event's implementation. It works fine... but... NOT EVERY TIME! Sometimes the markers get moved by various distances (mostly up or down) and then just keep these incorrect positions while the text is scrolled. I have no idea why and WHEN this happens. I was able to discover only these few things:
- you can reproduce this bug (move some markers from their correct positions) by dragging the vertical scrollbar of the code editor window very fast and agresively up and down (but sometimes it also fixes the positions...)
- you cannot fix a marker's position by editing the line on which it is placed (or even the marked text)
- you can fix the marker's position by deleting and restoring the ending "}" of the code block in which the marked code is placed (which causes the whole block of code to be reformatted)
- the view.ViewportTop is negative when the positions are calculated incorrectly (view is a WpfTextView class) and the Geometry "g" (see below) is getting the negative Bounds.Top too. (You can test it by attaching one VS to another and set a breakpoint)
Here is the piece of my code that calculates the positions and creates the markers (LayoutChanged event):
Geometry g = textViewLines.GetMarkerGeometry(span);
if (g != null)
{
GeometryDrawing drawing = new GeometryDrawing(_brush, _pen, g);
drawing.Freeze();
DrawingImage drawingImage = new DrawingImage(drawing);
drawingImage.Freeze();
Image image = new Image();
image.Source = drawingImage;
//Align the image with the top of the bounds of the text geometry
Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);
//_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, image, null);
Rect rect = new Rect(g.Bounds.Location, g.Bounds.Size);
Rectangle marker = new Rectangle();
marker.Margin = new Thickness(rect.X - 3, rect.Y - 2, 0, 0);
marker.Width = rect.Width + 6; marker.Height = rect.Height + 4;
marker.Fill = new SolidColorBrush(mark);
marker.RadiusX = marker.RadiusY = 5;
marker.Stroke = new SolidColorBrush(color);
_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative, span, null, marker, null);
}
This is basically the MSDN example for creating adornments, I'm not doing any magic here.
Please help!