如何自定义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
相关产品推荐
相关产品推荐

