0

你是我唯一的希望。我到处搜索,找不到任何可以帮助我解决这个问题的东西。

我为 Visual Studio (2010) 做了一个简单的代码标记插件。它只是找到要突出显示的代码的某些部分(通过正则表达式),从找到的匹配项中创建 Spans,然后为它们创建 Rectangle 装饰(在文本的背景中),随文本滚动。所有这些都是在 view.LayoutChanged 事件的实现中完成的。它工作正常......但......不是每次!有时标记会移动不同的距离(主要是向上或向下),然后在滚动文本时保持这些不正确的位置。我不知道为什么以及何时发生这种情况。我只能发现以下几点:

  • 您可以通过非常快速且积极地上下拖动代码编辑器窗口的垂直滚动条来重现此错误(将一些标记从其正确位置移动)(但有时它也会修复位置......)
  • 您无法通过编辑放置标记的行(甚至标记的文本)来修复标记的位置
  • 您可以通过删除和恢复放置标记代码的代码块的结尾“}”来修复标记的位置(这会导致整个代码块被重新格式化)
  • 当位置计算不正确(视图是 WpfTextView 类)并且几何“g”(见下文)也得到负 Bounds.Top 时,view.ViewportTop 为负数(您可以通过将一个 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 示例,我在这里没有做任何魔术。

请帮忙!

4

2 回答 2

0

我有同样的问题。如果你使用

_layer.AddAdornment(AdornmentPositioningBehavior.TextRelative,...);

不止一次你必须插入

Canvas.SetLeft(image, g.Bounds.Left);
Canvas.SetTop(image, g.Bounds.Top);

以前每次。

于 2013-11-27T17:30:20.017 回答
0

我刚刚花了一整天的时间在类似的问题上。

除了跨度移动问题之外,还有很多未记录的极端案例。更糟糕的是,似乎经过验证的解决方案往往会中断 VS 版本(尤其是从 roslyn 和 VS2015 开始)。我最喜欢的是以下内容:如果您在多行注释中多次按 Enter,则偶尔会删除装饰。好笑!

所以,唯一可行的方法是:不要试图超越 VS 编辑器,它会欺骗你。

相反,从 roslyn's 借用代码AdornmentManager<T>。它包含了很多我不得不重新发明的技巧,甚至更多我从未怀疑过的技巧,但它确实有效。您需要做的就是替换下面的代码

// add the visual to the adornment layer.

与您的(该部分是重构为可覆盖方法的良好候选者)。

PS我知道我有点晚了:)希望这可以为另一个可怜的灵魂节省一些时间。

于 2015-10-19T18:27:35.813 回答