You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何自定义Visual Studio 2022中折叠大纲区域的文本样式?

解决方案:自定义C++ #pragma region折叠行为与样式

一、核心思路

要实现自定义折叠文本、移除边框和修改样式,需要替换Visual Studio默认的大纲标记(Outlining Tag)——默认折叠文本由IOutliningTag控制,仅靠分类标记无法修改折叠状态的显示内容。我们需要实现自己的ITagger<IOutliningTag>来覆盖原有逻辑,同时通过格式定义调整折叠区域的外观。

二、实现步骤

1. 实现自定义大纲标记器

创建类生成自定义折叠标签,将默认折叠文本替换为// REGION:

using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Tagging;
using Microsoft.VisualStudio.Utilities;
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;

namespace Extension;

internal class PragmaRegionOutliningTagger : ITagger<IOutliningTag>
{
    private readonly ITextBuffer _buffer;

    public PragmaRegionOutliningTagger(ITextBuffer buffer)
    {
        _buffer = buffer;
    }

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged;

    IEnumerable<ITagSpan<IOutliningTag>> ITagger<IOutliningTag>.GetTags(NormalizedSnapshotSpanCollection spans)
    {
        if (spans.Count == 0) yield break;

        foreach (var span in spans)
        {
            foreach (var line in span.Snapshot.Lines)
            {
                var lineText = line.GetText().TrimStart();
                if (lineText.StartsWith("#pragma region", StringComparison.OrdinalIgnoreCase))
                {
                    var endRegionLine = FindEndRegionLine(line);
                    if (endRegionLine != null)
                    {
                        // 定义折叠范围:从region行末尾到endregion行开头
                        var collapseSpan = new SnapshotSpan(
                            line.End + 1,
                            endRegionLine.Start - 1);

                        // 自定义折叠显示文本
                        var collapsedForm = "// REGION";
                        // 折叠提示文本(hover时显示)
                        var collapsedHintForm = lineText.Substring("#pragma region".Length).Trim();

                        yield return new TagSpan<IOutliningTag>(
                            collapseSpan,
                            new OutliningTag(
                                isCollapsed: false,
                                isImplementation: false,
                                collapsedForm: collapsedForm,
                                collapsedHintForm: collapsedHintForm));
                    }
                }
            }
        }
    }

    // 查找对应的#pragma endregion行
    private ITextSnapshotLine? FindEndRegionLine(ITextSnapshotLine startLine)
    {
        var snapshot = startLine.Snapshot;
        for (int i = startLine.LineNumber + 1; i < snapshot.LineCount; i++)
        {
            var line = snapshot.GetLineFromLineNumber(i);
            var lineText = line.GetText().TrimStart();
            if (lineText.StartsWith("#pragma endregion", StringComparison.OrdinalIgnoreCase))
            {
                return line;
            }
        }
        return null;
    }
}

2. 注册大纲标记器提供者

为C/C++内容类型导出自定义标记器:

[Export(typeof(ITaggerProvider))]
[ContentType("C/C++")]
[TagType(typeof(IOutliningTag))]
internal class PragmaRegionOutliningTaggerProvider : ITaggerProvider
{
    public ITagger<T> CreateTagger<T>(ITextBuffer buffer) where T : ITag
    {
        if (buffer == null) return null;
        return buffer.Properties.GetOrCreateSingletonProperty(
            () => new PragmaRegionOutliningTagger(buffer)) as ITagger<T>;
    }
}

3. 移除折叠边框并自定义文本样式

通过EditorFormatDefinition修改折叠区域的外观:

using System.Windows.Media;
using Microsoft.VisualStudio.Text.Classification;
using Microsoft.VisualStudio.Utilities;
using System.ComponentModel.Composition;

[Export(typeof(EditorFormatDefinition))]
[Name("CustomOutliningCollapsedRegion")]
[DisplayName("自定义折叠区域样式")]
[UserVisible(true)]
[Order(After = "Default Priority")]
internal sealed class CustomOutliningCollapsedRegionFormat : EditorFormatDefinition
{
    public CustomOutliningCollapsedRegionFormat()
    {
        // 移除折叠边框
        BorderBrush = null;
        BorderThickness = new System.Windows.Thickness(0);
        // 自定义折叠文本颜色和字号
        ForegroundColor = Color.FromArgb(255, 71, 165, 10);
        FontSize = 10;
    }
}

// 可选:自定义折叠提示(hover时的文本样式)
[Export(typeof(EditorFormatDefinition))]
[Name("CustomOutliningCollapsedHint")]
[DisplayName("自定义折叠提示样式")]
[UserVisible(true)]
[Order(After = "Default Priority")]
internal sealed class CustomOutliningCollapsedHintFormat : EditorFormatDefinition
{
    public CustomOutliningCollapsedHintFormat()
    {
        ForegroundColor = Colors.Gray;
        FontSize = 9;
    }
}

4. 保留原有未折叠文本样式(可选)

如果你需要继续隐藏原#pragma region文本,可保留你原来的ClassificationTag相关代码,大纲标记器和分类标记器可共存。

三、关键说明

  • 大纲标记器控制折叠范围和显示文本,分类标记器控制未折叠时的文本样式,两者功能互补。
  • 示例中逐行查找#pragma endregion是基础实现,复杂场景可结合Visual Studio的C++语言服务做语法分析,提高准确性。
  • 样式定义的Name属性使用自定义名称即可生效,无需匹配内部固定值。

内容的提问来源于stack exchange,提问作者Lillo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.13 04:37:27