色分けをやってみたいんですけど…。

解決


たかみちえ  URL  2002-07-02 07:42:55  No: 1053

簡単なリッチエディットの色分けをやってみたくて、
  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)
とは、違いがないはずなんですけど…。

  この操作に関するミスって、どう言うものが考えられますか?


にしの  2002-07-02 09:05:03  No: 1054

ちょっと脇道。
Boyer-Mooreアルゴリズムは、場合によっては最初のテーブル作成で時間がかかる場合があります。
単純探索でも結構早く動作すると思いますよ。

本題に入ります。
Perform関数は、SendMessageのように見えて、そうではないようです。
ソースをみるとわかりますが、WindowProcを直に呼んでいます。
SendMessageに変えた部分、Performに直すとどうですか?
うまく動かないのでしょうか。


たかみちえ  URL  2002-07-02 23:30:53  No: 1055

> 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に変更しました。

を書いてます。もしかしてこれが原因ということはないですよね…。


にしの  2002-07-03 02:41:13  No: 1056

CFont[FoundPatternIndex]の中身はなんですか?
ちゃんと、TCharFormatになっていますか?
dwMaskを設定してありますか?
cbSizeに、SizeOf(TCharFormat)が入っていますか?
単独でPerformのテストをしたところうまくいくので、この部分だと思います。
Performした場合、ProcessMessagesは必要なさそうです。
# 動作は未確認ですが、ソースを見る限り、直接呼び出しているので。

BM法のコンポーネントは特に問題ないと思います。
RichEditのWindowProcを書き換えていると、問題が発生する可能性があります。


たかみちえ  URL  2002-07-03 09:23:04  No: 1057

そうですかぁ、やっぱりここかなぁ…。

  こういう関数をつくって、
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はそのままです。


にしの  2002-07-03 11:08:50  No: 1058

フォントサイズは、cbSizeでなくyHeightです。
cbSizeは、構造体のサイズを設定します。

これでうまくいきませんか?


にしの  2002-07-03 11:14:35  No: 1059

書き忘れです。
フォントサイズの指定では、値を20倍してください。
たとえば、9ポイントの指定では、180を代入します。


たかみちえ  URL  2002-07-04 01:55:20  No: 1060

ああー、ほんとだ…。
fontsizeとかの項目がないので、
ついそう設定して、そのままにしてしまいました。
ごめんなさい、ご迷惑おかけしました。解決しました。

  それにしてもなかなか早くなったものの、
それよりも早く検索して色分けしてしまうもの(TEditorやAFEditとか)はすごいですね、
エディタごと自前の描画とはいえ、どうしたらあそこまで早くできるのやら…。

  できるなら徐々に改良していって、"ただのRichEditでもここまでできるんだ"くらいのことを、やってみたいですね。
なにはともあれ、ありがとうございます。


※返信する前に利用規約をご確認ください。








  このエントリーをはてなブックマークに追加