7

我很难找出如何做到这一点,Visual Studio SDK 参考也不是很有帮助。

我试图弄清楚如何获得NormalizedSnapshotSpanCollectionXML 注释。我想在它们旁边放一个图标...我不想在每行旁边放一个图标,而只在每组的第一行旁边...

///<summary>SomeXML Comment</summary>   [ICON]
///<remarks>some remarks</remarks>
public void Foo()
{
    ///Some false XML comment line that does not get an icon.
}
4

1 回答 1

11

这是我能得到的,我认为它与您需要的非常相似。如果您有任何疑问,我将更新此内容并提供更多详细信息。

VS 2010 图标装饰

我从 VS 2010 SDK 网站的这个示例开始。它已经非常接近您的需要,但需要更多步骤。


下载C#版本,解压到文件夹,编译。要运行它并进行测试,您需要转到 Project > Properties > Debug

例如,您需要选择“启动外部程序”选项并设置 VS 2010 应用程序的路径C:\Program Files (x86)\Microsoft Visual Studio 10.0\Common7\IDE\devenv.exe

在命令行参数集中:/rootsuffix Exp

现在你应该可以运行它了,在打开的 VS 中创建一些示例项目,如果你在任何地方键入一个六位数的数字,00AA00它就会显示为具有相应颜色的矩形。关闭调试 VS 实例。


现在让我们编辑一些代码。在ColorAdornmentTagger.cs评论中定义#define HIDING_TEXT。这将在文本旁边显示装饰,而不是代替它。

在同一个文件中,您需要找到SnapshotSpan adornmentSpan初始化的位置并将行更改为:

SnapshotSpan adornmentSpan = new SnapshotSpan(colorTagSpans[0].End, 0);

这将在文本跨度之后而不是之前放置装饰。


ColorTagger.cs. 更改构造函数中的正则表达式,因此构造函数现在看起来像

    internal ColorTagger(ITextBuffer buffer)
        : base(
        buffer, 
        new[] { new Regex(@"/// <summary>.*", RegexOptions.Compiled | RegexOptions.CultureInvariant | RegexOptions.IgnoreCase) }
        )
    {
    }

这将设置正则表达式以识别方法注释行。

这个类中的其他方法我们不会使用,你可以评论它们或者返回一些随机的颜色。


在“ColorAdornment.cs”中。这是装饰 WPF 控件本身。首先将基类从 更改ButtonContentControl。将类的构造函数更改为

    internal ColorAdornment(ColorTag colorTag)
    {
        BitmapImage image = new BitmapImage(); 
        using (FileStream stream = File.OpenRead("c:\\temp\\sologo.png")) 
        { 
            image.BeginInit(); 
            image.StreamSource = stream; 
            image.CacheOption = BitmapCacheOption.OnLoad; 
            image.EndInit(); 
        }

        this.Content = new Image() { Margin = new Thickness(20,0,0,0), Width = 100, Height = 30, Source = image };
    }

您可以将图像路径更改为您需要的图像路径。我刚刚从 Wikipedia 下载了 SO 徽标并放入了我的临时文件夹。

编译并运行。您应该能够在调试 VS 实例中的注释旁边看到 SO 徽标。


一些额外的说明。

首先,通过这种方式,您只需获得一个工作原型,您应该重命名类并根据需要清理代码。

其次,当我调试它时,我的调试 VS 不时冻结。我认为这可能与IntraTextAdornmentTagger.cs

如果你也看到冻结,尝试用这种方式更新以下方法:

    protected void InvalidateSpans(IList<SnapshotSpan> spans)
    {
        if (spans.Count == 0)
            return;
        bool wasEmpty = false;
        lock (this.invalidatedSpans)
        {
            wasEmpty = this.invalidatedSpans.Count == 0;
            this.invalidatedSpans.AddRange(spans);
        }

        if (wasEmpty)
            this.view.VisualElement.Dispatcher.BeginInvoke(new Action(AsyncUpdate));
    }

和 AsyncUpdate 以这种方式:

    private void AsyncUpdate()
    {
        // Store the snapshot that we're now current with and send an event
        // for the text that has changed.
        if (this.snapshot != this.view.TextBuffer.CurrentSnapshot)
        {
            this.snapshot = this.view.TextBuffer.CurrentSnapshot;

            Dictionary<SnapshotSpan, TAdornment> translatedAdornmentCache = new Dictionary<SnapshotSpan, TAdornment>();

            foreach (var keyValuePair in this.adornmentCache)
                translatedAdornmentCache.Add(keyValuePair.Key.TranslateTo(this.snapshot, SpanTrackingMode.EdgeExclusive), keyValuePair.Value);

            this.adornmentCache = translatedAdornmentCache;
        }

        List<SnapshotSpan> spansCopy;
        lock (this.invalidatedSpans)
        {
            spansCopy = this.invalidatedSpans.ToList();
            this.invalidatedSpans.Clear();
        }

        List<SnapshotSpan> translatedSpans = spansCopy.Select(s => s.TranslateTo(this.snapshot, SpanTrackingMode.EdgeInclusive)).ToList();

        if (translatedSpans.Count == 0)
            return;

        var start = translatedSpans.Select(span => span.Start).Min();
        var end = translatedSpans.Select(span => span.End).Max();

        RaiseTagsChanged(new SnapshotSpan(start, end));
    }
于 2012-02-21T22:37:02.190 回答