画像ファイル
画像ファイル 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プロセス間通信(受信側)


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


はじめに
リッチテキストボックスを使って、HTMLのエディター等を作成した時、タグの中を色付けしたい場合がある。
タグが少ない場合はSeltext等を使用して簡単に色付けが行えるが、文章が長くタグの数が多い場合は、
この方法は信じられないほど、時間がかかる。
ここでは実際どのようにしたら速く色付けが出来るかサンプルを上げながら説明しよう。

文字列の操作を速くするには
本題の入る前に文字列操作に関して考えてみよう。
[課題 1]
「富士山には月見草が良く似合う」 と言う文字列に改行を加えて10、000個並べた文字列を作成しなさい。
文字列の加算を使用した普通の方法
VB6コード  文字の加算を使用した方法
For n = 1 To 10000
s = s + "富士山には月見草が良く似合う" & vbCrLf
Next
気の早い人はこう書き始めているかもしれない。
そこで更に条件を出す、 2行で書きなさい、ただし「:」は使ってはいけない。
そんなの無理だよと投げ出す人が殆どでしょう。
そんなことは有りません。
頭とReplaceを使へ
文字列の加算は時間がかかるのです。
VB6 文字の加算を使用した方法
s = String(10000, "a")
s = Replace(s, "a", "富士山には月見草が良く似合う" & vbCrLf)
これで出来るのです。
・String(10000, "a")は「a」を10000個並べる関数。
・Replace(s, "a", "富士山には月見草が良く似合う" & vbCrLf)は
その「a」を全て"富士山には月見草が良く似合う" & vbCrLf)に置き換えます。
たった2行で書けるのです。
これで驚いてはいけません、この処理にかかる時間を計って見ましょう、
最初の方法は、私の環境では9047msecつまり約9秒かかります。
2番目の方法は、なんと15msec(0.015秒)、単純計算で600倍のスピードです。
もう一つ早い方法をご紹介しよう。

Joinも仲間に入れろ
VB6のコード  Joinを使用した方法
Dim d(1 To 10000)
For n = 1 To 10000
  d(n) = "富士山には月見草が良く似合う" & vbCrLf
Next
s = Join(d)
この方法は2行では書けないけれどJoin関数を使う方法である。
Join関数は文字列を結合するのである。Join関数の詳細はMSDNを見ていただきたい。
この方法だと時間は40mseであるReplaceよりな遅いけれど、1番目の方法と比べると225倍の速さである。

文字列の操作を速くする 文字の位置を探す
[課題2]
上で作成した文字列で"富士山"の先頭の位置を全て探しなさい

Mid関数を使用した方法
VB6のコード   Mid関数を使用したコード
s1 = "富士山"
For n = 1 To Len(s) - Len(s1)
If Mid(s, n, Len(s1)) = s1 Then
'何かの処理
End If
Next
ここで「s」は上で求めた文字列です。
この方法だと私の環境では、141msec(0.14秒)かかります。

InStrを使へ
Instrを使用したコード
s1 = "富士山"
t = 0
Do
t = InStr(t + 1, s, s1)
If t = 0 Then Exit Do
'表示処理
Loop
InStrと言う関数を使用すると、処理時間は16msec(0.016秒)です。
なんと最初の処理の約9倍の速さです。
以上のことをふまえ文字列操作高速化の方法として次の注意すべき3点を上げる。
1、Replaceを使え。
2、Joinを使え。
3、Mid関数の代わりにInStrを使え。
文字列の操作を早くしたいと思われる方は、この教えを先ず頭にただきこもう。

応用問題を一つ
[課題 3]
上で作成した文字列の「富士山」の頭に「夜の」を挿入しなさい
そう、もう解ってきましたね。
VB6 のコード  Replaceを使用したコード
s = Replace(s,"富士山","夜の富士山")
一行で済むのです、しかも高速で。

RichTextの仕組み
さてここで本題に戻ってみよう。
RichTexBoxの仕様は
Word 2003: Rich Text Format (RTF) Specification, version 1.8
ただしこれはWord 2003の仕様なので、RichTextBoxの仕様とは若干異なる。
RichTextBoxは通常のTextとRtfと呼ばれるファイルの2重構造になっています。
Textの方は通常のテキストと全く同じですが、RtfはTextの他に、文字の色や大きさといった通常の
TextBoxでは出来ない設定を含んでいます。
つまりRichTextBoxを自由にコントロールしたい場合は、Rtfに付いて知る必要があるのです。

RichTextのRtfファイルを覗く
RichTextBoxのRtfの振る舞いを見るのは、RichTextBox上でテキストに色をつけたり、 フォントを変えたりした時の Rtfの変化を表示すると簡単にわかります。
そこでVbを使用してRtfを表示する道具を作ってみます。
作り方は簡単で、RichTexBoxのTextが変化したらそのTextRTFを別のTextBoxに書き込むと言う方法です。
こうするとRichTexBoxの振る舞いが全てわかります。
このソフトは「RTF忠太」と名前を付けて、コード付きでこのページの下でダウンロードできるようにして有ります。
興味のある人は試してみてください。

Rtfカラーテーブル
では実際にRichTexBoxの文字に色を付けるとTextRTFがどのように変化するか見てみましょう。
先ずRichTexBoxに 「abcde」 と書き込んで見ます。
TextRTFのコードは
{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset128 \'82\'6c\'82\'72 \'82\'6f\'83\'53\'83\'56\'83\'62\'83\'4e;}}
\viewkind4\uc1\pard\lang1041\f0\fs24 abcde
\par }
となります。
次に先頭の「a」を赤色に設定します。TextRTFのコードは
{\rtf1\ansi\deff0{\fonttbl{\f0\fnil\fcharset128 \'82\'6c\'82\'72 \'82\'6f\'83\'53\'83\'56\'83\'62\'83\'4e;}}
{\colortbl ;\red255\green0\blue0;}
\viewkind4\uc1\pard\cf1\lang1041\f0\fs24 a\cf0 bcde
\par }

となります。
違いは何でしょう、先ず「\viewkind4」の前に「{\colortbl ;\red255\green0\blue0;}」が挿入されています。
次に「\lang1041」の前に「\cf1」が、「bcde」の前に「\cf0」が挿入されています。
勘のいい人は既に解ったと思いますが、RichTextBoxのTextに色を付けると、「\viewkind4」の前に
カラーテーブルが挿入されるのです。
色を赤と青に設定すると、カラーテーブルは、
{\colortbl ;\red255\green0\blue0;\red0\green0\blue255;}
となります。
「\cf1」と言うようなカラー番号が挿入されていれば、その後の文字はそのカラー番号の文字になります。
そのカラー番号の色になります。更に黒のテーブル「\colortbl ;\red0\green0\blue0;」は省略されています。
そして黒のカラー番号は「\cf0」です。

ヘッダーの説明
ヘッダーについて少し説明しておきましょう。
{\fonttbl{\f0\fnil\fcharset128 \'82\'6c\'82\'72 \'82\'6f\'83\'53\'83\'56\'83\'62\'83\'4e;}
見て解る通りこれはフォントテーブルです、テキストがどのようなフォントで表示されるか表しています。
「\fcharset128」は 日本語フォント、続く 「\'82\'6c\'82\'72 \'82\'6f\'83\'53\'83\'56\'83\'62\'83\'4e」 は「MS Pゴシック」をShift-JISコードとして表している。
RichTextにおいて1バイト文字はそのまま2バイト文字は「\'xx\'yy」と「xx」はShift-JISコードの上位2バイト「yy」は
下位2バイトとして書かれるのである。

黒-デフォルトの色の省略
最初に色を設定しない前のRichTextの文字色は黒で、黒のカラーテーブルは省略されています。
ただしテキストを黒に設定した場合は、他の色と同じように黒のカラー番号も設定されます。

RichTextBoxの自動調整
RichTextBoxのRtfを設定したからといって、直ぐそれが反映されるとは限りません。
RichTextBoxにはRtfの文法のチェック機能があり、間違った設定や、省略出来る場合は、
Rtfが設定される前に変更や省略が行われます。
たとえば、カラーテーブルに色を設定しても、実際にその色が使用されていないと、カラーテーブルからその色が
消されます。
つまり{\colortbl ;\red255\green0\blue0;}というカラーテーブルを、RichTextBoxのTextRtfに挿入しても
実際にこの色が指定されなければ、このテーブルは自動的に消されてしまいます。
文字の最初の色の設定は「\lang1041\」の前に設定しますが、これをTextRtf上の色をつけたい文字の直ぐ前に
設定しても、自動的に「\lang1041\」の前に移してくれます。
上に書きましたが、2バイト文字はShift-JISコードで書かれますが、これを直接文字で書き込んでも
自動的にコードに変換してくれます。
つまりTextRtfに直接「富士山」と書き込んでも\'95\'78\'8e\'6d\'8e\'52と自動変換されます。
TextRIFを使った色付けでは実際にTextRIFを使ってテキストに色をつけてみましょう。
HTMLテキストのタグ<>の中の文字を赤に色付けするサンプルを考えて見ましょう。
手順は次のようになります。
1、カラーテーブルを消す。
2、新たにカラーテーブルを挿入する。
3、タグ<>の中の文字にカラー番号を挿入する。

カラーテーブルを削除する
VB6のコード  カラーテーブルを削除するコード
 'カラーテーブルを削除するコード
Dim s As String, ss As String
Dim t1 As Long, t2 As Long
s = RichTextBox1.TextRTF
t1 = InStr(s, "{\colortbl")
If t1 0 Then
  t2 = InStr(t1, s, "}")    'カラーテーブルが有った場合{の次の}を探す
  ss = Mid(s, t1, t2 - t1 + 1)  '{から}までを切り出す
  s = Replace(s, ss, "")   '{から}の文字を空白に置き換える
End If
こんな感じになります。この操作は1回だけなので、ReplaceやInSteの代わりにMid関数を使用しても構いません。

カラーテーブルの挿入
VB6のコード   カラーテーブルを挿入するコード
s = Replace(s, "\viewkind", "{\colortbl ;\red255\green0\blue0;}" _
& vbCrLf & "\viewkind")

タグの中にカラー番号をセット
VB6のコード タグの中にカラー番号をセットするコード

s = Replace(s, "<", "<\cf1")
s = replace(s, ">", "\cf0>")
RichTextBox1.TextRTF = s
どうです簡単でしょう、'Mid関数で  <、> を探して'等と考えていた人はあまりの簡単さに驚くでしょう。
VBの中で後から追加された関数で、APIに近いものは処理速度も相当に速くなっています。
今回はその代表格Replace、InStr、Joinを使いましたが、その他の関数として次のような関数があります。
Split -------Joinの逆の関数で、デリミタ(カンマなど)で区切られた文字列を配列に入れる。
InStrRev ---InStrと同じであるが逆方向に文字列を探す。
等があります。

読み出しと保存
リッチテキストのファイルからの読み込みと保存は、極めて簡単である。
読み込みは、
RichTextBoxにテキストファイルを読み込む
RichTextBox1.LoadFile "Text.txt" '読み込み

拡張子が「txt」の場合は、テキストファイルを、「Rtf」の場合はリッチテキストを読み込む。

書き込み
VB6 RichTextBoxからテキストファイルを書き出す
RichTextBox1.SaveFile "Text.txt"
拡張子が「txt」の場合は、テキストファイルを、「Rtf」の場合はリッチテキストを書き込む。
この簡単さを利用して、次のような処理が可能となる。
あるテキストファイルの文字列を他の文字列で置換したい。
たとえば、「富士山」という文字を含むテキストのファイルが有り、の文字を全て「美人」と
言う文字に置き換えたいとする。
通常はファイルをオープンして、ループで読み込み、その読み込んだ文字列を置き換える
操作になるがリッチテキストを使うと、

ファイル内容の書き換え
VB6 ファイルの内容の書き換へ
RichTextBox1.LoadFile FileName
RichTextBox1.Text = Replace(RichTextBox1.Text, "富士山", "美人")
RichTextBox1.SaveFile FileName, 1
のたった三行でこの処理が可能となる、しかも高速である。

VB.NETでRichTextBoxでの任意の文字を任意の色付け方法を下にリンクしました、VB6の方も覗かれると
参考になると思います。

画像 ダウンロード →「RTF忠太」
画像ファイル