簡単なリッチエディットの色分けをやってみたくて、
NiftyのフォーラムでBM法複数文字列検索コンポーネントなどを見つけ、
いろいろ勉強してやってみました。
でも、肝心のフォントの指定がうまくいかないんです。
2次元配列にTCharFormatの配列をつくって、
それから見つかった文字列に、配列の中のTCharFormatを、
EM_SETCHARFORMATでくっつける…。という方法です。
でも、EM_SETCHARFORMATを送っても、文字列の色が変わらないんです。
BiginUpdateをコメントアウトしてみて、範囲選択はしっかりされているようですけど…。
SendMessage(Wnd,EM_SETCHARFORMAT, SCF_SELECTION, lParam(@CFont[FoundPatternIndex]));
CFontはTCharFormatの2次元配列、
FoundPatternIndexは、BM法検索コンポーネントの、見つかったパターンの登録番号、
Wndはあらかじめ取得した、自分自身のハンドルです
(Performも最終的にSendMessageをよぶはずだから、それより一瞬でも早くなるかなぁって…^^;)。
とくにそう言うサンプル
(こことか http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=33)
とは、違いがないはずなんですけど…。
この操作に関するミスって、どう言うものが考えられますか?
ちょっと脇道。
Boyer-Mooreアルゴリズムは、場合によっては最初のテーブル作成で時間がかかる場合があります。
単純探索でも結構早く動作すると思いますよ。
本題に入ります。
Perform関数は、SendMessageのように見えて、そうではないようです。
ソースをみるとわかりますが、WindowProcを直に呼んでいます。
SendMessageに変えた部分、Performに直すとどうですか?
うまく動かないのでしょうか。
> Boyer-Mooreアルゴリズムは、場合によっては最初のテーブル作成で時間がかかる場合があります。
> 単純探索でも結構早く動作すると思いますよ。
そうなんですか、
なら、一種類の文字検索のときは、そのほうがよさそうですね。
でも、今回は、複数の文字(15種類)を検索しようとしてるので、
標準方法よりこっちのほうがはやそうです^^;
文字列の中を探すのも、一回で済みますし。
(このコンポーネント、複数の文字列をすばやく検索できるように、BM法を拡張したものだそうです)
> Perform関数は、SendMessageのように見えて、そうではないようです。
> ソースをみるとわかりますが、WindowProcを直に呼んでいます。
そうなんですかぁ、Personalなので、ソースはないです。勉強になります。
で、全部の記述をPerformに変えてみたんですけど、だめでした。
いろがえの部分を、SelAttributesに変えてみたら、いちおう普通にできたので、他のところでは失敗してないみたいです。
TCharFormatのところも、デバッグで調べてみましたけど、問題ないみたいです。
(途中で見失ったということはないと思います…、たぶん…)
PerForm(EM_EXSETSEL, 0, lParam(@CR));
// SelAttributes.Color := CFont[FoundPatternIndex].crTextColor; // これだと成功
PerForm(EM_SETCHARFORMAT, SCF_SELECTION, lParam(@CFont[FoundPatternIndex]));//書式決定
Application.ProcessMessages;
こんな感じです。
範囲の検索はこんな感じです。
11..14:begin // (か[か{か'が検索された
EndFound := AnsiStrPos(FoundPos,EndChar[FoundPatternIndex - 11]);
if not Assigned(EndFound) then Continue; // 終了符が見つからない(脱出)
CR := NewCharRange(fp,EndFound - @str[0] + 1);
end;
// FoundPos コンポーネントが文字を発見した位置ポインタ
// EndChar ),],},'などが入ったPCherの配列(いちいち定数をキャストするより早い?)、色分け目的の文字
// str エディタないの文章そのもののポインタ
// NewCharRange CharRange構造体を一行で書く^^;関数
最初に
with Edit,EBMSearch.Create(Self) do begin
// Edit エディタ
// EBMSearch BM法複数文字列検索コンポーネント。
// FDelphiにあったソースではコンパイルできなかったので、registerをつけて、継承さきをTComponentに変更しました。
を書いてます。もしかしてこれが原因ということはないですよね…。
CFont[FoundPatternIndex]の中身はなんですか?
ちゃんと、TCharFormatになっていますか?
dwMaskを設定してありますか?
cbSizeに、SizeOf(TCharFormat)が入っていますか?
単独でPerformのテストをしたところうまくいくので、この部分だと思います。
Performした場合、ProcessMessagesは必要なさそうです。
# 動作は未確認ですが、ソースを見る限り、直接呼び出しているので。
BM法のコンポーネントは特に問題ないと思います。
RichEditのWindowProcを書き換えていると、問題が発生する可能性があります。
そうですかぁ、やっぱりここかなぁ…。
こういう関数をつくって、
function NewCharFormat(const Color:TColor=0;
const Effects:TFontStyles=[];const FontSize:Cardinal=0): TCharFormat;
var
Masks,Effect : Cardinal;
CF : TCharFormat;
begin
with CF do begin
Masks := 0;
cbSize := SizeOf(CF);
if (fsBold in Effects) then inc(Masks,CFM_BOLD);
if (fsItalic in Effects) then inc(Masks,CFM_ITALIC);
if (fsUnderline in Effects) then inc(Masks,CFM_UNDERLINE);
if (fsStrikeout in Effects) then inc(Masks,CFM_STRIKEOUT);
Effect := Masks;
if Color <> 0 then begin
inc(Masks,CFM_COLOR);
crTextColor := Color;
end;
if FontSize <> 0 then begin
inc(Masks,CFM_SIZE);
cbSize := FontSize;
end;
dwEffects := Effect;
dwMask := Masks;
end;
Result := CF;
end;
これを、
for i := 0 to High(CFont) do
CFont[i] := NewCharFormat(clFuchsia,[fsBold],9);
とやってCharFormatを設定してます。
怪しいのはここかなとも思ったんですけど、
デバッグで見たところ、
ちゃんとcbSizeは、HSPのサイトで見かけた60(この構造体の正しいバッファサイズらしいです)になってるし、
dwMaskは$4千万(色)+$8千万(サイズ)+1(ボールド)になってるみたいです。
CFM_BOLDとかは、RichEdit.pasを見たところ、
CFE_BOLDと同じ数値みたいなので、Effectにもそのまま代入しました。
デバッグで一行ずつ経過を見てみたら、ちゃんと変なところに行ったり、スキップしたりはしてないようです。
どこかおかしいでしょうか?
> Performした場合、ProcessMessagesは必要なさそうです。
いちおう念のためにつけておいてました。
色分けが遅くなって、そのあいだに応答なしとみなされて、強制終了されちゃうと困るので。
あと、WindowProcはそのままです。
フォントサイズは、cbSizeでなくyHeightです。
cbSizeは、構造体のサイズを設定します。
これでうまくいきませんか?
書き忘れです。
フォントサイズの指定では、値を20倍してください。
たとえば、9ポイントの指定では、180を代入します。
ああー、ほんとだ…。
fontsizeとかの項目がないので、
ついそう設定して、そのままにしてしまいました。
ごめんなさい、ご迷惑おかけしました。解決しました。
それにしてもなかなか早くなったものの、
それよりも早く検索して色分けしてしまうもの(TEditorやAFEditとか)はすごいですね、
エディタごと自前の描画とはいえ、どうしたらあそこまで早くできるのやら…。
できるなら徐々に改良していって、"ただのRichEditでもここまでできるんだ"くらいのことを、やってみたいですね。
なにはともあれ、ありがとうございます。
ツイート | ![]() |