I want to create a simple Adorner that marks a selected element with a bounding box. I want it to be sharp and be exactly one pixel outside the target content. I found some useful code, but it does not work exactly as I wanted it to.
The OnRender method of my SelectAdorner is:
Rect adornedElementRect = new Rect(AdornedElement.DesiredSize);
SolidColorBrush renderBrush = new SolidColorBrush(Colors.Transparent);
Pen renderPen = new Pen(new SolidColorBrush(Colors.LightBlue), 1);
double halfPenWidth = renderPen.Thickness / 2;
// Create a guidelines set
GuidelineSet guidelines = new GuidelineSet();
guidelines.GuidelinesX.Add(adornedElementRect.Left + halfPenWidth);
guidelines.GuidelinesX.Add(adornedElementRect.Right + halfPenWidth);
guidelines.GuidelinesY.Add(adornedElementRect.Top + halfPenWidth);
guidelines.GuidelinesY.Add(adornedElementRect.Bottom + halfPenWidth);
drawingContext.PushGuidelineSet(guidelines);
drawingContext.DrawRectangle(renderBrush, renderPen, adornedElementRect);
The problem is that the bounding box is not aligned properly around the content (see second and third item). I want the result to be the one from the bottom item in the picture below.
Any ideas how can I achieve what I want?
Also, it would be nice to have the Adorner working in the same way with renderPen.Thickness
greater than 1, in case I need that.
Thanks for the help.
The following code needs to be added before creating the GuidelineSet:
adornedElementRect = new Rect(
adornedElementRect.Left - halfPenWidth,
adornedElementRect.Top - halfPenWidth,
adornedElementRect.Width + renderPen.Thickness,
adornedElementRect.Height + renderPen.Thickness
);
The problem comes from the fact that adornedElementRect overlaps AdornedElement when the pen thickness is taken into consideration. The value of AdornedElement.DesiredSize corresponds to the outer edge of the border. That means that the Adorner is drawn half over the border and half outside the border. The GuidelineSet then aligns the right side of vertical edges and the bottom side of horizontal edges to pixel boundaries. This makes the drawing look sharp, however the edges are moved either to the inside, either to the outside of the AdornedElement. This is what creates the artifact.
When adding the specified changes to adornedElementRect, then it is drawn outside and right next to the AdornedElement. Now, the GuidelineSet aligns the Adorner similarly with the Border control. See this link for more information about how WPF draws the content on the screen.