VS2010中的文本相关装饰:它们有时显示在不正确的位置
本文关键字:显示 位置 不正确 文本 VS2010 | 更新日期: 2023-09-27 18:00:37
你是我唯一的希望。我到处找了,就是找不到任何能帮助我的东西。
我为Visual Studio(2010)做了一个简单的代码标记插件。它只是找到代码的某些部分来突出显示(通过Regex),从找到的匹配中创建Span,然后为它们创建矩形装饰(在文本的背景中),并随文本滚动。所有这些都是有目共睹的。LayoutChanged事件的实现。它运行良好。。。但是不是每一次有时标记会移动不同的距离(主要是向上或向下),然后在滚动文本时保持这些不正确的位置。我不知道为什么和什么时候会发生这种事。我只能发现以下几件事:
- 您可以通过快速地上下拖动代码编辑器窗口的垂直滚动条来重现这个错误(将一些标记从正确的位置移动)(但有时它也会修复位置…)
- 无法通过编辑标记所在的行(甚至标记的文本)来固定标记的位置
- 您可以通过删除和恢复放置标记代码的代码块的末尾"}"来修复标记的位置(这会导致整个代码块被重新格式化)
- 视图。当位置计算不正确(视图是WpfTextView类)并且几何体"g"(见下文)获得负边界时,ViewportTop为负。Top也是。(您可以通过将一个VS附加到另一个VS并设置断点来测试它)
这是我的一段代码,它计算位置并创建标记(LayoutChanged事件):
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);
}
这基本上是MSDN创建装饰的例子,我在这里没有做任何魔术。
请帮忙!
我也遇到了同样的问题。如果您使用
_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative,...);
一旦你必须插入
Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);
以前的每一次。
我刚刚花了一整天的时间讨论类似的问题。
除了跨度移动问题外,还有很多未记录的角落案例。更糟糕的是,似乎已被证明的解决方案往往会在never VS版本中崩溃(尤其是从roslyn和VS2015开始)。我最喜欢的是以下内容:如果在多行注释中多次按enter键,装饰偶尔会被删除。令人捧腹的
所以,唯一有效的方法是:不要试图智胜VS编辑器,它无论如何都会欺骗你。
相反,可以借用roslyn的AdornmentManager<T>
中的代码。它包含了很多我必须重新发明的技巧,还有更多我从未怀疑过的技巧,但它确实有效。你所需要做的就是替换下面的代码
// add the visual to the adornment layer.
使用您的方法(该部分是重构为可重写方法的好候选者)。
附言:我知道我有点迟到了:)希望这能为另一个可怜的人节省一些时间。