0

我知道如何使用 VS Extensibility 来获取整个活动文档的文本。不幸的是,这只会让我得到文本,并没有给我格式,我也想要那个。

例如,我可以得到一个,IWpfTextView但一旦我得到它,我不知道该怎么处理它。是否有实际从中获取所有格式的示例?我只对文本前景色/背景色真正感兴趣,仅此而已。

注意:我在每次编辑时都需要格式化文本,所以很遗憾,不能使用剪贴板进行剪切和粘贴。

4

2 回答 2

1

这是我的不是最简单的解决方案。TL;DR:您可以跳转到https://github.com/jimmylewis/GetVSTextViewFormattedTextSample上的代码。

VS 编辑器使用“分类”来显示具有特殊含义的文本段。然后可以根据语言和用户设置对这些分类进行不同的格式化。

有一个 API 用于获取文档中的分类,但它对我不起作用。或者其他人,显然。但是我们仍然可以通过 获得分类ITagAggregator<IClassificationTag>,如前面的链接中所述,或者在这里:

[Import]
IViewTagAggregatorFactoryService tagAggregatorFactory = null;

// in some method...
var classificationAggregator = tagAggregatorFactory.CreateTagAggregator<IClassificationTag>(textView);
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
var tags = classificationAggregator.GetTags(wholeBufferSpan);

有了这些,我们就可以重建文档了。重要的是要注意某些文本没有分类,因此您必须将所有内容拼凑在一起。

同样值得注意的是,在这一点上,我们不知道这些标签中的任何一个是如何格式化的——即渲染过程中使用的颜色。如果你愿意,你可以定义你自己的映射IClassificationType到你选择的颜色。或者,我们可以询问 VS 使用IClassificationFormatMap. 同样,请记住,这受用户设置、浅色与深色主题等的影响。

无论哪种方式,它都可能看起来像这样:

// Magic sauce pt1: See the example repo for an RTFStringBuilder I threw together.
RTFStringBuilder sb = new RTFStringBuilder();
var wholeBufferSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, 0, textBuffer.CurrentSnapshot.Length);
// Magic sauce pt2: see the example repo, but it's basically just 
// mapping the spans from the snippet above with the formatting settings 
// from the IClassificationFormatMap.
var textSpans = GetTextSpansWithFormatting(textBuffer);

int currentPos = 0;
var formattedSpanEnumerator = textSpans.GetEnumerator();
while (currentPos < wholeBufferSpan.Length && formattedSpanEnumerator.MoveNext())
{
    var spanToFormat = formattedSpanEnumerator.Current;
    if (currentPos < spanToFormat.Span.Start)
    {
        int unformattedLength = spanToFormat.Span.Start - currentPos;
        SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, unformattedLength);
        sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
    }

    System.Drawing.Color textColor = GetTextColor(spanToFormat.Formatting.ForegroundBrush);
    sb.AppendText(spanToFormat.Span.GetText(), textColor);

    currentPos = spanToFormat.Span.End;
}

if (currentPos < wholeBufferSpan.Length)
{
    // append any remaining unformatted text
    SnapshotSpan unformattedSpan = new SnapshotSpan(textBuffer.CurrentSnapshot, currentPos, wholeBufferSpan.Length - currentPos);
    sb.AppendText(unformattedSpan.GetText(), System.Drawing.Color.Black);
}

return sb.ToString();

希望这对您正在做的任何事情都有帮助。示例 repo 将询问您是否希望在每次编辑后将格式化文本放入剪贴板,但这只是一种肮脏的方式,我可以测试并看到它有效。这很烦人,但这只是一个 PoC。

于 2017-04-18T20:45:33.733 回答
1

可能最简单的方法是选择所有文本并将其复制到剪贴板。VS 将富文本放入剪贴板,因此当您在其他地方粘贴时,您将获得颜色(假设您在目标中处理富文本)。

于 2017-04-17T21:13:16.813 回答