VisualBasic あれやこれや、VB2005、.NET 画像ファイル
画像ファイル VB.NET RichTextBoxテキスト色付け高速化計画
RichTextBox関係
1RichTextBoxの不思議
2テキスト色付け高速化計画
3VB.NET RichTextBox1
4VB.NET RichTextBox 2

VB.NET C#全般
1羊の皮を着た狼 VB.NET
2Form1、Form2の相互参照
3Form1、Form2の相互参照 2
4VB.NET C# データ型の基本
5VB.NET C# 文字列
6VB.NET タイマー精度
7BackgroundWorkerの魅力1..
8BackgroundWorkerの魅力2..
9VB6のタイマー
10コントロールの配列をインデクサ..
11コントロールの配列はジェネリク..
12インデクサ(C#、VB.NET)
13インデクサでBit操作
14Unicode 入門
15デリゲート入門
16マルチスレッド入門
17イベント入門
18デリゲートとイベント
18インターフェースの基本

RS-232C関係
1RS-232Cの基礎
2RS-232Cの何が変わった..
3SerialPortクラス
4Unicode(ユニコード)の壁
5マルチスレッドの壁
6RS-232C サンプルコード
7RS-232CのHEXモニタ
8RS-232C 送信モジュール
9RS-232Cのループテスト
10RS-232Cのピンチェンジ..

Socket通信
1C#、VB2005 でSocket通信
2サーバー 複数接続

プロセス間通信
1プロセス間通信(送信側)
2プロセス間通信(受信側)


質問、意見はこちらに
画像ファイル


RichTextBox
今回はVB.NETを使用したRichTextBoxの色付けを考えて見ましょう。
考え方は、VB6と殆ど同じですが、今回はより実用に近い方法を紹介します。
最初はHTMLテキストのタグの色付けを行います。

スキーマ(設計図)を作成する
  1. リッチテキストボックスのRtfからカラーテーブルを抜き出す。
  2. 抜き出したカラーテーブルに設定したい色を追加する。
  3. 色を追加したカラーテーブルを元のRtfの中のカラーテーブルと入れ替える。
  4. 設定したいカラーの色番号を、新しいカラーテーブルから取得する。
  5. Rtf上で現在設定してある色を待避する。
  6. タグ一斉変換「"<」;タグを「<\cfx 」に入れ替える。
  7. 「>」タグを「\cf0 >」に入れ替える。
  8. 待避した色を元に戻す。
カラーテーブルの構造
カラーテーブルは通常下の様な形式になっている。
{\colortbl ;\red0\green0\blue255;\red255\green0\blue0;\red0\green128\blue0;}
この中の、
"\red0\green0\blue255;"
これはお分かりであろう色のRGBを表す、上の例は青である。
"\colortbl"は正式には"カラーテーブルのコントロールワード" と言う。
\red0、\green0、\blue255はそれぞれ、赤のインデックス、緑のインデックス、青のインデックスと呼ぶ。
頭に\が付く文字はコントロールワードを表しており、上場合は青、赤、緑の順番で並んでいる。
もちろん各インデックスはのRichTextBoxのテキストの色の設定で変わる。
このインデックスは";(セミコロン)"で区切られているが、この順番で1、2、3、.....と 番号が付けられる、たとえば文字の色だと\cf1、\cf2、\cf3...と、バックカラーは\cb1、\cb2、\cb3、... というコントロールワードになり、色付けが開始される文字の前に挿入される。
\cf0はでデフォルト値で黒ある、\cf0はカラーテーブルが無くても使用できるが、その他\cf1等は、 カラーテーブルとリンクしている。
たとえば"<div>"の中のdivを赤に設定したい場合、<\cf0 >となる、ただしこれは、 上のカラーテーブルを適用した場合である。
divの後に挿入される\cf0はこれ以降の文字が黒に設定されると言うことであり、 この結果は<div>となる。
つまりタグの中身を有る色\cfx(xはカラー番号)に設定したい場合は、"<"を 全て"<\cfx "に変換して、 ">"を"\cf0 >"に変換すればよいことになる。
(注意)\cfx、\cf0の後には半角の空白が必要です。

特定の文字を特定の色を設定する
では黒以外の色に設定された "Hello world;"の中のHelloの文字色を赤に 設定したい場合はどうなるのだろうか?
この場合は最初に"Hello world"が何色に設定されているかを調べる必要が有る。
なぜなら、Helloの文字に色を設定した後、world以降の色を元に戻さなければならないからだ。
それには、Rtfの中のHelloの文字の位置を取得して、それより前の"\cf"を探し、それに続く 番号を取得してそれをHelloの後ろに挿入すればよいことになる。
プログラム的には、最初に戻す方の色のコントロールワードを先に挿入してから、設定する色の コントロールワードを挿入する、これは一見逆の様に見えるが、先に設定のコントロールワードを 挿入してしまうと、HelloのRtfの先頭からの文字数が変化してしまい、戻す為のコントロール語の挿入が 多少面倒になるからだ、もちろん計算で出来ないことは無い。
戻す色を挿入した後は、設定したい色のコントロールワードをHelloの前に挿入すればよいことになる。
もしフォントテーブルに赤が(\red255\green0\blue0)が無い場合は、赤を追加する必要が有る。
更にフォントテーブルが無い場合は、フォントテーブルそのものを作成する必要が有る。
実際テキストの色が黒だけの場合フォントテーブルが無いのである。
その辺のところは実際のコードを参照していただきたい。
"\cfx Hello \cfy world"
これがその設定である、\cfxは赤のカラー番号で、\cfyは赤を設定する前に既に設定されていた テキストの色の番号で有る。
通常\cfxの後に空白を設ける、\cfxの後に数字が来た場合、それが番号の続きなのか、 テキスト文なのか区別出来ないので、当然のことであろう。
ただし\cfxの後に\が来た場合は空白は必要ない、たとえ空白を入れても自動的に削除される。
最後にもう一つ重要なことが有る、フォントテーブルに赤が無くて追加した場合でも、 又既にフォントテーブルの中に赤がある場合でも、赤の番号を取得する必要が有る。
なぜなら挿入する"\cfx"の文字を作成する為に、"x"の値を知る必要があるからだ。
フォントテーブルが無くて自分で追加した場合は、設定したい文字は必ず\cf1となる、念のために。

具体的な構想

1、リッチテキストボックスのRtfからカラーテーブルを抜き出す。
Rtfの中からカラーテーブルを探すことは簡単である。
先ず「{\colortbl」を探し次に 来る「}」を探せばいいのである。
RichTextBox内にはカラーテーブルは一つ存在するか、全く存在しなかのどちらかである。
次の関数で引数にRtfを入れるとカラーテーブルが返ってくるものとしよう。
VB.NETのコード
Public Function GetColorTbl(ByRef strRtf As String) As String
この関数はカラーテーブルが無ければ、空白文字を返すものとする。

2、抜き出したカラーテーブルに設定したい色を追加する。
これはチョッと工夫が必要である、先ず関数の仕様を決めてしまう。
VB.NETのコード
Public Function AddColor(ByRef strRtf As String, _
       ByVal objColor As Object) As String
この関数の第1引数にRtfを設定し第2引数にColorクラスの色を入れると、 カラーテーブルに色が追加されるものとする。
さて追加したい色を仮に赤とするなら「\red255\green0\blue0」を挿入することになる。
実際にプログラムで設定する場合は、Colorクラスを使用するから、Colorクラスから、 このRtfの色の形式に直す関数が必要となる。
VB.NETのコード
Public Function GetColorString(ByVal objColor As Object) As String
この関数の引数にColorクラスを入れると、Rtf形式の色要素が返ってくるものとする。
strRtfColor = GetColorString(Color.Red)
等として呼び出せば"\red255\green0\blue0"が返ってくるものとする。
引数の形式がObjectになっているのは、引数にColorクラスの色か、又はバイト配列で255,0,0等と 入れるとRtfのカラー文字列が返って来る仕様にした為である。
さてここで色を挿入すると書いたが、既にカラーテーブルにその色が存在する否か、 挿入する前に調べる必要が有る。
そのために、カラーテーブルから色コントロールワードを取得して、文字の配列に入れる関数を作ろう。
Private Function GetColorArray(ByVal strRtf As String) As String()
この関数で、既に設定されている色の文字列が、配列で返される、設定色が存在するか否かは、 この配列に色を調べれば良いことになり、もし存在していなかったら配列の上限を一つ増やして、 そこに新しい色を加え、その後で配列を元にカラーテーブルを作成する。
これで新しいカラーテーブルの完成である。

3、色を追加したカラーテーブルを元のRtfの中のカラーテーブルと入れ替える
テーブルの入れ替えは、次の関数で行う。
VB.NETのコード
Public Function ChangeCtbl(ByVal strRtf As String, _
ByVal strNewCtbl As String) As String
見ての通り、第1引数にRtfを第2引数に、2で作成した新しいカラーテーブルを入れる。
これは簡単である。

4、設定したいカラーの色番号を、新しいカラーテーブルから取得する。
カラーテーブルに新しく色を追加した場合でも、既に色が存在する場合でも、テキストに設定 する色の番号を取得する必要が有る。
これは3で作成した、色を配列に入れる関数が使用出来る、配列の番号と色の番号が一致するからである。

5、Rtf上で現在設定してある色を待避する。
タグの色付けに関しては最初に説明した、先ず現在の色を待避させる。
これは"<"を"<\cfx"に置換した場合に既にタグに色が設定されていた場合の 二重設定を防ぐ為である。
この方法はチョッとトリッキーな方法を使おう。
strRtf = strRtf.Replace("<\cf", Chr(2))
Rtf内の"<\cf"をキャラクターコードの2に全て変換するコードである。
Chr(2)はRtf上では絶対使うことの無い文字であり、この文字に一時置き換える。
こうすると色が既に設定してあるタグは全てChr(2)に変換される為に、次のタグの変換が 行われないのである。
当然カラー番号が挿入された後元に戻しておく必要が有る。

6、タグ一斉変換「<」タグを「<\cfx 」に入れ替える。
xはその時で異なる番号である
タグの<を一斉に書き換えることは簡単である。
設定したカラーの番号がstrColorString(例:\cf2)であると仮定すると、
strRtf = strRtf.Replace("<", strColorNoString)
これだけである、更にタグの>を元に戻す色に置き換えなくてはならない、 strRtf = strRtf.Replace(">", "\cf0>")
となる、この場合タグの<>はデフォルトの色、つまり黒を想定している。

7、「>」タグを「\cf0 >」に入れ替える。
これはもうお分かりであろう。

8、待避した色を元に戻す。
最後は待避したタグの色を元に戻せばおしまいである。
strRtf = strRtf.Replace(Chr(2), "<\cf")

ユニコードとSift-Jisの2バイトコード
VB.NETでは文字は全てユニコードで取り扱う、ところがRtfでは日本語の文字は、 シフトJISコードをASCII形式で表した表記法が使われます。
しかもRtfの場合、"\'上位バイト\'下位バイト"と変換されます。
たとえば"あ"は\'82\'a0となります。
"abc"などの1バイト文字はそのままです。
したがってRtf内で有る2バイト文字を探す場合は、先ずユニコードからSift-Jisに変換して それが2バイト文字なら上下のバイトに"\'"を付加してRtfの文字形式に直す。
VB.NETのコード
Public Shared Function getEncodeString(ByVal strS As String) As String
この関数でユニコードの文字をRtf形式に直します。
この関数はタグの色付けには使用しませんが、Rtfの中から文字を検索して色付けを 行う場合に使用します。
ユニコードに関しては「 Unicode入門 」を御覧戴きたい。
さて次は関数の実装である。

画像ファイル