RichTexBoxで文字に色付けする
投稿者 るきお  (社会人)
投稿日時
2010/10/10 19:54:27
こんにちは。
RichTextBoxの表示で"abc"の部分だけを青くするには次のようにします。
"efg"を赤くするには次のようにします。
以上の例では文字列"abc"や"efg"の検索に正規表現を使っているので対象の文字列に記号が含まれている場合は一工夫必要な場合があります。(正規表現のことがわかっていれば特別な工夫は必要ないです。)
参考に、".Tranin"を赤くする例を紹介します。
RichTextBoxの表示で"abc"の部分だけを青くするには次のようにします。
Dim pattern As String = "abc"
Dim matches = System.Text.RegularExpressions.Regex.Matches(RichTextBox1.Text, pattern)
For Each match As System.Text.RegularExpressions.Match In matches
Dim start As Integer = match.Index
Dim length As Integer = match.Length
RichTextBox1.Select(start, length)
RichTextBox1.SelectionColor = Color.Blue
Next
"efg"を赤くするには次のようにします。
Dim pattern As String = "efg"
Dim matches = System.Text.RegularExpressions.Regex.Matches(RichTextBox1.Text, pattern)
For Each match As System.Text.RegularExpressions.Match In matches
Dim start As Integer = match.Index
Dim length As Integer = match.Length
RichTextBox1.Select(start, length)
RichTextBox1.SelectionColor = Color.Red
Next
以上の例では文字列"abc"や"efg"の検索に正規表現を使っているので対象の文字列に記号が含まれている場合は一工夫必要な場合があります。(正規表現のことがわかっていれば特別な工夫は必要ないです。)
参考に、".Tranin"を赤くする例を紹介します。
Dim pattern As String = "\.Train"
Dim matches = System.Text.RegularExpressions.Regex.Matches(RichTextBox1.Text, pattern)
For Each match As System.Text.RegularExpressions.Match In matches
Dim start As Integer = match.Index
Dim length As Integer = match.Length
RichTextBox1.Select(start, length)
RichTextBox1.SelectionColor = Color.Red
Next
投稿者 るきお  (社会人)
投稿日時
2010/10/10 21:38:10
失礼しました。「書き込み中に」色を付けたいのですね。
上述の例はボタンなどをクリックしたタイミングで色を付ける場合です。
しかしながら、RichTextBoxはどういう意地悪なのか書き込み中に簡単に色を変える方法が提供されていません。
がんばってプログラムすれば可能なのですがなかなか難しいですし、プログラムの量もかなり多くなります。
少しチャレンジしてみましたが、どうも妙です。色が変わる単語(abc, efg, .Train)を打った直後にはスペースが入力できなくなってしまいました。ほかにももっといろいろやると問題がたくさんありそうです。
そんなプログラムでも多少の参考にはなると思いますので載せておきます。
誰か完成させてください。
上述の例はボタンなどをクリックしたタイミングで色を付ける場合です。
しかしながら、RichTextBoxはどういう意地悪なのか書き込み中に簡単に色を変える方法が提供されていません。
がんばってプログラムすれば可能なのですがなかなか難しいですし、プログラムの量もかなり多くなります。
少しチャレンジしてみましたが、どうも妙です。色が変わる単語(abc, efg, .Train)を打った直後にはスペースが入力できなくなってしまいました。ほかにももっといろいろやると問題がたくさんありそうです。
そんなプログラムでも多少の参考にはなると思いますので載せておきます。
誰か完成させてください。
Public Class Form1
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim adapter As New Rtf.RichTextBoxAdapter(RichTextBox1)
adapter.ColorTexts.Add("abc", Color.Blue)
adapter.ColorTexts.Add("efg", Color.Red)
adapter.ColorTexts.Add("\.Train", Color.Green)
End Sub
End Class
Namespace Rtf
'RTFの仕様
'http://msdn.microsoft.com/en-us/library/aa140301(v=office.10).aspx#rtfspec_12
'RTFの例
'{\rtf1\ansi\ansicpg932\deff0\deflang1033\deflangfe1041{\fonttbl{\f0\fswiss\fcharset0 Arial;}{\f1\fnil\fcharset128 MS UI Gothic;}}
'{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
'\viewkind4\uc1\pard\lang1041\f0\fs18 AAAAA\par
'\cf1 abc\cf0\par
'BBBBB\par
'\cf2 efg\cf0\par
'CCCCC\f1\par
'}
Public Class RichTextBoxAdapter
Public WithEvents Source As RichTextBox
Public ColorTexts As New Dictionary(Of String, Color)
Public Sub New(ByVal source As RichTextBox)
Me.Source = source
End Sub
Private Sub source_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Source.TextChanged
If ColorTexts.Count = 0 Then
Return
End If
'TextBox1.Text = RichTextBox1.Rtf
Static stopper As Boolean
If stopper Then
Return
End If
stopper = True
Dim typedSender As RichTextBox = sender
Dim currentPos As Integer = typedSender.SelectionStart
Dim rtf As New Rtf.Document(typedSender.Rtf)
rtf.ClearTextMark()
For Each Text As String In ColorTexts.Keys
Dim color As Color = ColorTexts(Text)
rtf.MarkText(Text, color)
Next
typedSender.Rtf = rtf
typedSender.SelectionStart = currentPos
stopper = False
End Sub
End Class
Public Class Document
Public Rtf As String
Public ColorTable As ColorTable
Public Sub New(ByVal rtf As String)
Me.Rtf = rtf
Me.ColorTable = New ColorTable(rtf)
End Sub
'テキストの色をすべてクリアする。
Public Sub ClearTextMark()
Dim pattern As String = "\\cf[1-9]+?\s+?"
Me.Rtf = System.Text.RegularExpressions.Regex.Replace(Me.Rtf, pattern, "")
pattern = "\\cf0"
Me.Rtf = System.Text.RegularExpressions.Regex.Replace(Me.Rtf, pattern, "")
End Sub
''' <summary>
''' Textは正規表現のエスケープ付きで指定してください。
''' たとえば、「Dim」が対象の時は単に"Dim"で良いですが、
''' .Trainが対象の時は"\.Train"とする必要があります。
''' </summary>
''' <param name="text"></param>
''' <param name="color"></param>
''' <remarks></remarks>
Public Sub MarkText(ByVal text As String, ByVal color As Color)
'colorが現在のColorTableにあるか確認
Dim colorIndex As Integer = Me.ColorTable.IndexOf(color) + 1
If colorIndex < 1 Then
'存在しなければ追加する
Me.ColorTable.Add(color)
colorIndex = Me.ColorTable.IndexOf(color) + 1
End If
'色がついたテキストは次のようになっている。
'ここでcf1の1がColorIndex
'\cf1 abc\par
Dim result As String = "\cf" & colorIndex & " " & text & "\cf0"
Me.Rtf = System.Text.RegularExpressions.Regex.Replace(Me.Rtf, text, result)
End Sub
投稿者 るきお  (社会人)
投稿日時
2010/10/10 21:39:16
長いので分割しています。上の続きです。
Public Sub RenderAll()
RenderColorTable(Me.ColorTable)
End Sub
Public Sub RenderColorTable(ByVal table As ColorTable)
Dim newTable As String = table.ToString
'ColorTableの存在チェック
Dim match = System.Text.RegularExpressions.Regex.Match(Me.Rtf, ColorTable.RegExPattern)
If match.Success Then
'カラーテーブルが存在する場合は置換
Me.Rtf = System.Text.RegularExpressions.Regex.Replace(Me.Rtf, ColorTable.RegExPattern, newTable)
Else
'存在しない場合は挿入
Dim pos As String = Me.Rtf.IndexOf("}}") 'これでいいんだろうか?RTFの仕様がよくわからない。
Me.Rtf = Me.Rtf.Insert(pos + 2, newTable)
End If
End Sub
Public Overrides Function ToString() As String
RenderAll()
Return Me.Rtf
End Function
Shared Narrowing Operator CType(ByVal value As Rtf.Document) As String
Return value.ToString
End Operator
End Class
'ColorTableの例
' {\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;
'\red0\green255\blue0;
'\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;
'\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;
'\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;
'\red128\green128\blue0;\red128\green128\blue128;\red192\green192\blue192;}
Public Class ColorTable
Inherits List(Of Color)
Public Const RegExPattern As String = "\{\\colortbl\s*?;(.*?)\}"
'Public Colors As New List(Of Color)
Public Sub New(ByVal rtf As String)
'ColorTable部分の抜出
Dim pattern As String = RegExPattern
Dim match = System.Text.RegularExpressions.Regex.Match(rtf, pattern)
If Not match.Success Then
Return
End If
Dim entries As New List(Of String)(Split(match.Groups(1).Value, ";"))
pattern = "\\red(?<red>[0-9]+)\\green(?<green>[0-9]+)\\blue(?<blue>[0-9]+)"
For Each entry In entries
If Len(entry) = 0 Then
Continue For
End If
'このときentryは次のような形式
'\red0\green255\blue0
Dim params = System.Text.RegularExpressions.Regex.Match(entry, pattern)
Me.Add(Color.FromArgb(params.Groups("red").Value, params.Groups("green").Value, params.Groups("blue").Value))
Next
End Sub
Public Overrides Function ToString() As String
'{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;}
Dim result As New System.Text.StringBuilder(16)
For Each Color In Me
result.Append(";\red" & Color.R & "\green" & Color.G & "\blue" & Color.B)
Next
If result.Length = 0 Then
Return ""
End If
Return "{\colortbl " & result.ToString & ";}"
End Function
End Class
End Namespace
投稿者 (削除されました)  ()
投稿日時
2010/10/12 17:09:13
(削除されました)
投稿者 XPMAX2008  (中学生)
投稿日時
2010/10/14 21:06:03
るきおさん、ありがとうございます。
まさに僕が探し求めていたのは、こういうことです。
調べてもなかなか出てこないので・・・
ここで質問してよかったです。
ちなみに、.Trainや、abcの後の色が赤や緑などに変更されたままだったので、この文を足して直しました。
まさに僕が探し求めていたのは、こういうことです。
調べてもなかなか出てこないので・・・
ここで質問してよかったです。
ちなみに、.Trainや、abcの後の色が赤や緑などに変更されたままだったので、この文を足して直しました。
Private Sub RichTextBox1_TextChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RichTextBox1.TextChanged
RichTextBox1.SelectionColor = Color.Black
End Sub
投稿者 XPMAX2008  (中学生)
投稿日時
2011/1/9 13:34:28
Dim pattern As String = "efg"
Dim matches = System.Text.RegularExpressions.Regex.Matches(RichTextBox1.Text, pattern)
For Each match As System.Text.RegularExpressions.Match In matches
Dim start As Integer = match.Index
Dim length As Integer = match.Length
RichTextBox1.Select(start, length)
RichTextBox1.SelectionColor = Color.Red
Next
このコードで、「"」の色を茶色(Color.Brown)に変えるにはどうすればよいですか?
投稿者 よねKEN  (社会人)
投稿日時
2011/1/9 14:03:43
> このコードで、「"」の色を茶色(Color.Brown)に変えるにはどうすればよいですか?
Dim pattern As String = """"
文字列リテラルで「"」を表現するときは二重にした「""」を使います。
Dim pattern As String = """"
文字列リテラルで「"」を表現するときは二重にした「""」を使います。
投稿者 xvmm  (中学生)
投稿日時
2011/1/9 14:37:01
よねKENさん。ありがとうございます。
あと、
VB.NETの、「'」や、HTMLの「<!-- *** -->」間を緑にする方法を教えてください。
あと、
VB.NETの、「'」や、HTMLの「<!-- *** -->」間を緑にする方法を教えてください。
投稿者 よねKEN  (社会人)
投稿日時
2011/1/9 16:41:33
> VB.NETの、「'」や、HTMLの「<!-- *** -->」間を緑にする方法を教えてください。
「"」じゃなくて「'」ですか?
' HTMLのコメント用(「<!-- あいう -->」などにマッチする)
Dim HtmlComment As String = "<!--.*?-->" ' ポイントは「?」で最短一致にしているところ。
' VBの文字用 (「'あ'」などにマッチする)
' 「'」で囲まれた任意の文字列(ただし「'」自身は含まない)
Dim VBChar As String = "'[^']*'"
ついでに、VBの文字列の抽出用も以下に記載しておきます。
' VBの文字列用
' ("あいう"や"あいう""えお"などにマッチする)
Dim VBString As String = """(""""|[^""])*"""
上記の各正規表現を理解するには・・・
MSDNの「正規表現言語要素」(下記URL)の解説を読んでみてください。
※正直説明がわかりやすいとは言えないので他のサイトも含めて
「正規表現」でいろいろ調べてみてください。
http://msdn.microsoft.com/ja-jp/library/az24scfc.aspx
「"」じゃなくて「'」ですか?
' HTMLのコメント用(「<!-- あいう -->」などにマッチする)
Dim HtmlComment As String = "<!--.*?-->" ' ポイントは「?」で最短一致にしているところ。
' VBの文字用 (「'あ'」などにマッチする)
' 「'」で囲まれた任意の文字列(ただし「'」自身は含まない)
Dim VBChar As String = "'[^']*'"
ついでに、VBの文字列の抽出用も以下に記載しておきます。
' VBの文字列用
' ("あいう"や"あいう""えお"などにマッチする)
Dim VBString As String = """(""""|[^""])*"""
上記の各正規表現を理解するには・・・
MSDNの「正規表現言語要素」(下記URL)の解説を読んでみてください。
※正直説明がわかりやすいとは言えないので他のサイトも含めて
「正規表現」でいろいろ調べてみてください。
http://msdn.microsoft.com/ja-jp/library/az24scfc.aspx
投稿者 よねKEN  (社会人)
投稿日時
2011/1/9 16:54:33
勘違いしていたので、補足です。
> VB.NETの、「'」や、HTMLの「<!-- *** -->」間を緑にする方法を教えてください。
勘違いしてました。「'」の方はVBのコメントのことをお聞きになりたいのですね。
(VB.NETの文字の表現は"あ"cのように書きます。C#の文字の表現'あ'と勘違いしてました)
Dim VBComment As String = "'.*\n" ' 「'」で始まって改行までがコメント
(ちなみにVBのコメントにはREMキーワードを使った書き方もありますが、
最近使う人はあまりいないので無視しちゃっても構わないと思います。)
> VB.NETの、「'」や、HTMLの「<!-- *** -->」間を緑にする方法を教えてください。
勘違いしてました。「'」の方はVBのコメントのことをお聞きになりたいのですね。
(VB.NETの文字の表現は"あ"cのように書きます。C#の文字の表現'あ'と勘違いしてました)
Dim VBComment As String = "'.*\n" ' 「'」で始まって改行までがコメント
(ちなみにVBのコメントにはREMキーワードを使った書き方もありますが、
最近使う人はあまりいないので無視しちゃっても構わないと思います。)
RichTextboxで、書き込み中に、指定の文字(.Train , .FreeObjectなど)に色付けすることはできないでしょうか。
”abc”を青
”efg”を赤
にする方法を教えてください。