7

#regionVisual Studioでディレクティブのテキストの色を変更する簡単な方法を長い間探した結果、簡単な方法はないと結論付けました。

ステートメントの色を変更する方法と、折りたたまれた領域の色を変更する方法を知って#regionいますが、領域の説明とともにテキストの色を変更したいと思います。それで:

#region Some text   <--- all this text should be in a different color

public void Test()
{
}

#endregion          <--- this too

多くの人がこのようなものを探しているようです-VS2008で拡張された領域のタイトルの色を変更する方法を参照してください。

そのため、色を変更するための単純なVisualStudioアドインの作成を検討してきました。ただし、、、、、などSnapshotのクラスがあるためTagger、思ったよりも複雑です。ClassifierWpfTextViewCreationListenerAdornmentLayer

簡単に言えば、どこから始めればいいのかわかりません!私はMSDNサイトでいくつかのチュートリアルに従いましたが、私がやろうとしていることには複雑すぎるようです。

誰かが私にこれを行う最も簡単な方法を教えてもらえますか?つまり。VSSDK内のどのクラス/メソッド/イベントを使用する必要がありますか。UIなどで色をカスタマイズできなくてもかまいません。VS2010を使用しています。

編集:mztoolsのWebサイトを私に勧めてもらいました。私もそこを見ていきます。regionまた、StackOverflowのsの構文強調表示は、私が望んでいるものとほぼ同じであることに気づきました。

4

2 に答える 2

13

私は最終的に、少なくともVS2010の解決策を思いつきました。#regionこれを' 'および' 'タグの色付けに使用しまし#endregionたが、同様のソリューションをVisualStudioウィンドウのすべてのテキストコンテンツに適用できるはずです。

この種の問題IViewTaggerProviderは、ソースコードの一部に「分類」のタグを付けることで解決できるようです。Visual Studioは、その分類でタグ付けされたテキストのスタイルを提供します。これは、ユーザーが[ツール]>[オプション...]>[環境]>[フォントと色]を使用して目的のスタイルに変更できます。


Taggerプロバイダーは次のようになります。

[Export(typeof(IViewTaggerProvider))]
[ContentType("any")]
[TagType(typeof(ClassificationTag))]
public sealed class RegionTaggerProvider : IViewTaggerProvider
{
    [Import]
    public IClassificationTypeRegistryService Registry;

    [Import]
    internal ITextSearchService TextSearchService { get; set; }

    public ITagger<T> CreateTagger<T>(ITextView textView, ITextBuffer buffer) where T : ITag
    {
        if (buffer != textView.TextBuffer)
            return null;

        var classType = Registry.GetClassificationType("region-foreground");
        return new RegionTagger(textView, TextSearchService, classType) as ITagger<T>;
    }
}

これにより、ITaggerオブジェクトが作成されます。このオブジェクトは、Visual Studioのテキストビューを指定すると、指定された分類タイプでテキストの一部にタグを付けます。これはすべてのテキストビュー(つまり、ソースコードエディタ、「結果の検索」ウィンドウなど)で機能することに注意してください。ContentType属性を編集することでこれを変更できる場合があります( C#?だけに)。


分類タイプ(この場合は「region-foreground」)は次のように定義されます。

public static class TypeExports
{
    [Export(typeof(ClassificationTypeDefinition))]
    [Name("region-foreground")]
    public static ClassificationTypeDefinition OrdinaryClassificationType;
}

[Export(typeof(EditorFormatDefinition))]
[ClassificationType(ClassificationTypeNames = "region-foreground")]
[Name("region-foreground")]
[UserVisible(true)]
[Order(After = Priority.High)]
public sealed class RegionForeground : ClassificationFormatDefinition
{
    public RegionForeground()
    {
        DisplayName = "Region Foreground";
        ForegroundColor = Colors.Gray;
    }
}

このOrder属性は、テキストのスパンにも適用される可能性のある他の分類と比較して、分類がいつ適用されるかを決定します。は、[ツール]>[オプション... ]ダイアログDisplayNameで使用されます。


分類が定義されると、ITaggerクラスはビューのテキストを検索し、見つかったテキストの該当するセクションの分類を提供できます。

ViewLayoutChanged簡単に言えば、その仕事は、提供されたテキストビューのコンテンツが変更されたときに発生するテキストビューのイベントをリッスンすることです(たとえば、ユーザーが何かを入力したため)。

次に、テキストを検索して、関心のあるテキストの領域(「スパン」と呼ばれる)を探す必要があります。#regionここでは、またはのいずれかを含む行のスパンを返します#endregion。これは単純にしていますが、TextSearchService一致を見つけるために使用されるものは、正規表現を使用して検索することもできます。

最後に、Visual Studioが検出したテキストのタグを取得するための、と呼ばれるメソッドが提供されますGetTags()。特定のスパンコレクションに対して、これは分類タグ付きのテキストスパン、つまり特定の方法で分類する必要があるスパンの領域を返します。

そのコードは次のとおりです。

public sealed class RegionTagger : ITagger<ClassificationTag>
{
    private readonly ITextView m_View;
    private readonly ITextSearchService m_SearchService;
    private readonly IClassificationType m_Type;
    private NormalizedSnapshotSpanCollection m_CurrentSpans;

    public event EventHandler<SnapshotSpanEventArgs> TagsChanged = delegate { };

    public RegionTagger(ITextView view, ITextSearchService searchService, IClassificationType type)
    {
        m_View = view;
        m_SearchService = searchService;
        m_Type = type;

        m_CurrentSpans = GetWordSpans(m_View.TextSnapshot);

        m_View.GotAggregateFocus += SetupSelectionChangedListener;
    }

    private void SetupSelectionChangedListener(object sender, EventArgs e)
    {
        if (m_View != null)
        {
            m_View.LayoutChanged += ViewLayoutChanged;
            m_View.GotAggregateFocus -= SetupSelectionChangedListener;
        }
    }

    private void ViewLayoutChanged(object sender, TextViewLayoutChangedEventArgs e)
    {
        if (e.OldSnapshot != e.NewSnapshot)
        {
            m_CurrentSpans = GetWordSpans(e.NewSnapshot);
            TagsChanged(this, new SnapshotSpanEventArgs(new SnapshotSpan(e.NewSnapshot, 0, e.NewSnapshot.Length)));
        }
    }

    private NormalizedSnapshotSpanCollection GetWordSpans(ITextSnapshot snapshot)
    {
        var wordSpans = new List<SnapshotSpan>();
        wordSpans.AddRange(FindAll(@"#region", snapshot).Select(regionLine => regionLine.Start.GetContainingLine().Extent));
        wordSpans.AddRange(FindAll(@"#endregion", snapshot).Select(regionLine => regionLine.Start.GetContainingLine().Extent));
        return new NormalizedSnapshotSpanCollection(wordSpans);
    }

    private IEnumerable<SnapshotSpan> FindAll(String searchPattern, ITextSnapshot textSnapshot)
    {
        if (textSnapshot == null)
            return null;

        return m_SearchService.FindAll(
            new FindData(searchPattern, textSnapshot) {
                    FindOptions = FindOptions.WholeWord | FindOptions.MatchCase
                });
    }

    public IEnumerable<ITagSpan<ClassificationTag>> GetTags(NormalizedSnapshotSpanCollection spans)
    {
        if (spans == null || spans.Count == 0 || m_CurrentSpans.Count == 0)
            yield break;

        ITextSnapshot snapshot = m_CurrentSpans[0].Snapshot;
        spans = new NormalizedSnapshotSpanCollection(spans.Select(s => s.TranslateTo(snapshot, SpanTrackingMode.EdgeExclusive)));

        foreach (var span in NormalizedSnapshotSpanCollection.Intersection(m_CurrentSpans, spans))
        {
            yield return new TagSpan<ClassificationTag>(span, new ClassificationTag(m_Type));
        }
    }
}

簡潔にするために、名前空間とusingステートメントは省略しました。これらは通常、の形式Microsoft.VisualStudio.Text.*です。これらを使用できるようにするには、最初にVisual Studio2010SDKをダウンロードする必要があります。


私はこのソリューションを過去数か月間問題なく使用しています。

私が気付いた制限の1つは、色が「ブレンド」されていないため、不透明度が100%未満の色は、スパン内の既存の色を「フェードアウト」しないことです。これは、構文の強調表示を維持するのに役立つ場合があります。

また、キーを押すたびにドキュメントが繰り返し検索されるように見えるため、その効率についてもほとんどわかりません。VisualStudioがこれを何らかの形で最適化するかどうかを確認するための調査は行っていません。大きなファイル(>〜1000行)でVisual Studioの速度が低下していることに気付きましたが、Resharperも使用しているため、これをこのプラグインだけに帰することはできません。

これは主に当て推量を使用してコーディングされているため、物事を明確化または簡素化したり、コードのパフォーマンスを向上させたりする可能性のあるコメントやコード変更を歓迎します。

于 2012-05-29T12:47:41.887 に答える
0

Visual Studioアドインプロジェクトから始めることができると思います。これは、Visual Studioオブジェクトモデルと見なされていたEnvDTEを使用します。ここで、MSDNドキュメントを見つけてください:http: //msdn.microsoft.com/en-us/vstudio/ bb968855 EnvDTE を使用して、デバッガー、コードエディターなどのVisualStudioの動作を制御できます。

于 2012-03-14T08:17:28.360 に答える