WPFのRichTextBoxで、特定の文字の文字色を変更してみた。
どもです。
今回は、WPFのRichTextBoxコントロールの文字色を変更する方法について紹介します。
WindowsフォームアプリケーションのRichTextBoxコントロールではなく、WPFのRichTextBoxコントロールですので、そこは間違えないようお願いします。
0. 作業環境
今回のエントリでは、以下の環境で作業を行います。
項目 | 内容 |
---|---|
OS | Windows10 Pro(22H2) |
CPU | i7-8700 |
メモリ | 16GB |
IDE | Visual Studio Commnuity 2022(64bit) version 17.3.6 |
対象のフレームワーク | .NET Framework 4.7.2 |
1. やってみる内容
今回は、RichTextBox内の特定の文字列の文字色を変更してみます。
具体的には、RichTextBoxコントロール内にgoogletest実行時にコンソール上に表示される文字列を表示し、(極力)同じ色になるよう文字に色をつけてみます。
こんなカンジに色付けします。
2.やってみる
RichTextBox内の特定の文字列に色を付けるためには、以下の手順を実施します。
- 特定の文字列の出現位置/範囲を決定する。
- 決定した出現位置/範囲に対して文字色を設定する。
各手順について、使用する関数や使用方法、実装を示していきます。
2.1. 特定の文字列の出現位置/範囲を決定する
「特定の文字列の出現位置/範囲を決定する」ためには、以下の手順を実施します。
- RichTextBox内の任意の文字列の開始位置を取得する。
- RichTextBox内の任意の文字列の終了位置を取得する。
- RichTextBox内の任意の文字列に対する「範囲」取得する。
- 取得した「範囲」の文字列と「特定の文字列」を比較、一致しているか確認する。
- 一致していた場合には、「任意の文字列の開始位置」が「特定の文字列の出現位置」とする。
- 一致していない場合には、次の「任意の文字列の開始位置を取得する」処理を実行する。
これらの処理を実行するコードは、以下のようになります。
//RichTextBox内の任意の文字列の開始位置を取得する。
TextPointer start = richTextBox.Document.ContentStart;
//RichTextBox内の任意の文字列の終了位置を取得する。
TextPointer stop = start.GetPositionAtOffset(textData.Length);
ここで、変数textDataは、「特手の文字列」に対応する変数です。
//RichTextBox内の任意の文字列に対する「範囲」取得する。
var wrapRange = new TextRange(start, stop);
//取得した「範囲」の文字列と「特定の文字列」を比較、一致しているか確認する。
var wrapText = wrapRange.Text; //「範囲」の文字列を取得
if (wrapText.Equals(textData))
{
//一致していた場合...
}
else
{
//一致していなかった場合
}
少し補足をすると、「RichTextBox内の任意の文字列の開始位置を取得する」際にアクセスしているプロパティ「Document.ContentStart」は、RichTextBoxの内容の先頭位置に対応します。先頭位置から任意の文字数だけ後ろに移動した位置は、GetPositionAtOffset()メソッドを使用します。「任意の文字列の終了位置」は、「開始位置」に対応する変数startのGetPositionAtOffset()メソッドにアクセスして取得しています。
2.2. 決定した出現位置/範囲に対して文字色を設定する
これは、先述のコード内wrapRange変数のApplyPropertyValue()メソッドを使用します。
具体的なコードは、以下の通りです。
wrapRange.ApplyPropertyValue(TextElement.ForegroundProperty, color);
ApplyPropertyValue()メソッドの対1引数に指定している値により、設定したい内容を指定します。今回は選択範囲の文字色を変更するため、TextElement.ForegroundPropertyを指定します。設定可能な値と、それに対応する設定内容は、Micorosoftのページを参照してください。
2.3. 処理全体
ここまでで紹介したコードをまとめたものが、以下のモノです。
private void HighLightText(string textData, SolidColorBrush color)
{
int leftLen = 0;
TextPointer start = richTextBox.Document.ContentStart;
do
{
TextPointer stop = start.GetPositionAtOffset(textData.Length);
var wrapRange = new TextRange(start, stop);
var wrapText = wrapRange.Text;
if (wrapText.Equals(textData))
{
wrapRange.ApplyPropertyValue(TextElement.ForegroundProperty, color);
start = stop;
}
else
{
start = start.GetPositionAtOffset(1);
}
leftLen = start.GetOffsetToPosition(richTextBox.Document.ContentEnd);
} while ((0 < leftLen) && (textData.Length < leftLen));
}
上述のコードでは、RichTextBoxの内容全体を走査して、該当した文字列全てに対して同じ文字色を設定するため、do~while文でループしています。
3. 実行結果
先述のコードを用いて、googletest実行時にコンソール上に表示される文字列の結果を色付けした結果が、以下です。
色そのものを完全に再現はできていませんが、色付けする箇所は同一にできていると思います。
4. まとめ
今回は、WPFのRichTextBoxを用いて、指定した文字列の色を変更する方法について紹介しました。
RichTextBoxの部分的な文字列の書式の変更を行うために必要な処理は、基本的には
- 変更範囲を特定・取得する
- 変更範囲に対して、書式を設定する
です。
WPFの場合には、「変更範囲を特定・取得する」際には、RichTextBoxのDocumentプロパティ(FlowDocumentオブジェクト)のGetPositionAtOffset()メソッド、およびGetPositionAtOffset()メソッドを使用し、TextRangeオブジェクトで特定します。
また、書式の設定には、ApplyPropertyValue()メソッドを使用します。
これらのプロパティ、メソッド、およびオブジェクトを使用することで、書式の変更を行う手順を実現できるようになります。
この記事が、誰かの助けになれば幸いです。
ではっ!
Ex.公開しています
本エントリの内容、コードやサンプルをGitHunにて公開しています。エントリ中には書ききれなかった内容がありますので、コチラも是非さんしょうして下さい。
ディスカッション
コメント一覧
まだ、コメントがありません