RichEditで、英単語の途中で改行させるには?


かんとく  2010-09-17 19:17:30  No: 39171

お世話になっております。

XP,2007です。

RichEditで、行の終わり付近で、スペースを入れて英単語を入力すると、単語の終わりがその行におさまらない長さの場合、スペースの位置で改行され、自動的に次の行に単語が表示されてしまいます。

これを、行の最後まで単語が表示され、単語の途中でも改行されるようにするには、どうしたらよいでしょうか。

よろしくお願いします。


  2010-09-17 20:11:45  No: 39172

検証する環境がないのでリンク先だけ
https://www.petitmonte.com/bbs/answers?question_id=2641

さらに、WB_ISDELIMITERなんかも見ると
いい感じに改行できるかもしれません。VC++ですが
http://rararahp.cool.ne.jp/cgi-bin/lng/vc/vclng.cgi?print+200301/03010004.txt


かんとく  2010-09-17 20:22:33  No: 39173

ありがとうございます。

教えていただいた
https://www.petitmonte.com/bbs/answers?question_id=2641
は、自分でも見ていたんですが、Cのコードらしく、Delphiでどうしたらよいか分かりませんでした。

int CALLBACK MyEditWordBreakProc(LPTSTR lpch,int ichCurrent, int cch,  int code){
return 0;
}

function MyEditWordBreakProc(lpch:string,ichCurrent:integer,cch:integer,code:integer):integer;
begin
  result:=0;
end;

RichEdit1->Perform( EM_SETWORDBREAKPROC,0,(LPARAM)MyEditWordBreakProc);

RichEdit1.Perform( EM_SETWORDBREAKPROC,0,(LPARAM)MyEditWordBreakProc);

みたいな感じで試してみましたが、エラーが出ます。

Cは分からないので、これ以上分かりません。

引き続き、よろしくお願いします。


tor  2010-09-17 22:20:00  No: 39174

WordBreakProcの置き換えは、真面目にやろうとするとCR+LFの組み合わせを判別したり、
Ctrl+Left, Ctrl+Right のアルゴリズムも自分で実装しないといけないので
違和感なく動かすためにはけっこうチューニングが大変そうですね。

EM_SET/GETWORDBREAKPROCEXならデフォルトの処理関数が利用できるかと思ったけれど
やっぱり自分で登録しないとnilのままだったり。

とりあえず試してみたコード。uses節にRichEditとMathが必要です。

uses RichEdit, Math;

function MyWordBreakProc(lpch: PChar; ichCurrent, cch, code: Integer): Integer; stdcall;
begin
  case code of
    WB_CLASSIFY:  // 現在位置の文字種別を判定する
      // 実際には呼ばれてないようなので、これで内容が正しいかどうかは不明
      if lpch[ichCurrent] = ' ' then
        Result := WBF_ISWHITE
      else
        Result := WBF_BREAKAFTER or WBF_BREAKLINE;
    WB_ISDELIMITER: // 現在位置の文字が区切り文字か判定する
      Result := 0;
    WB_LEFT, WB_LEFTBREAK: // 単語の先頭/前の単語の終わりを左に探す
      Result := ichCurrent; // すべての文字が単語の先頭
    WB_MOVEWORDLEFT: // Ctrl+Leftで左に動く時に呼ばれる
      Result := Max(ichCurrent - 1, 0); // とりあえず1文字だけ戻す
    WB_RIGHT, WB_RIGHTBREAK: // 次の単語の先頭/単語の終わりを右に探す
      Result := Min(ichCurrent + 1, cch - 1); // 次の単語は常に1文字右
    WB_MOVEWORDRIGHT: // Ctrl+Rightで右に動くときに呼ばれる
      Result := Min(ichCurrent + 1, cch - 1); // とりあえず1文字だけ進める
    else // ここには来ないはず
      Result := 0;
  end;
end;

procedure TForm1.FormShow(Sender: TObject);
begin
  RichEdit1.Perform(EM_SETWORDBREAKPROC, 0, LPARAM(@MyWordBreakProc));
end;


かんとく  2010-09-18 04:02:10  No: 39175

ありがとうございます。

試してみましたが、
(@MyWordBreakProc)のところで、
「変数が必要です」というエラーが出ます。

(lpch: PChar; ichCurrent, cch, code: Integer)
に何か値を入れないといけないんでしょうか?

EM_SETWORDBREAKPROC  や  LPARAM  を調べてみましたが、よく分かりませんでした。

すみませんが、引き続き、お願いします。


tor  2010-09-18 06:48:09  No: 39176

> (@MyWordBreakProc)のところで、
> 「変数が必要です」というエラーが出ます。

MyWordBreakProcをフォームのメソッドとして定義していませんか?
メソッドにすると関数の型が合わないのでそのエラーが出ます。
提示した例のとおり、ただの関数として定義してください。
× function TForm1.MyWordBreakProc(...)
○ function MyWordBreakProc(...)
呼び出し規約(stdcall)を付けるのも忘れずに。

参考までに、LPARAM(@MyWordBreakProc) という式の意味について
・Cのキャストは 「(型名)式」ですが、Delphiでは「型名(式)」になります。
・@を付ける理由についてはヘルプの「文と式での手続き型」を参照。
これがないと関数呼び出しとみなされて「実パラメータが足りません」のエラーになります。


かんとく  2010-10-01 19:32:41  No: 39177

お返事遅れてすみません。

教えていただいたとおり、
× function TForm1.MyWordBreakProc(...)
○ function MyWordBreakProc(...)
が原因でエラーが出ていたようです。

ただ、ボックスの右端でスペースキーを押すと、1回目は、次の行にカーソルが出ますが、もう一度スペースキーを押すと、カーソルが消えてしまいます。

なんとなく、元の行の右の奥の方にカーソルが行っているような感じがします。
そのままもう一度スペースキーを押すと、次の行にカーソルが出ます。スペースは、この行に3個あります。
しかし、もう一度スペースキーを押すと、カーソルが消えてしまいます。

このように、スペースキーを押すたびに、カーソルが出たり消えたりを繰り返します。

何か必要な処理がされていないのでしょうか。

よろしくお願いします。


tor  2010-10-01 20:46:35  No: 39178

そのあたりの細かい挙動は、MyWordBreakProcの中身を気に入るまで調整するしかありません。だからチューニングが大変だと書いたわけで……

私の書いたサンプルは、「すべての文字が単語の区切りとなる」という単純なルールで実装したもので
文字列の中身はちゃんと見ていないし、空白文字などの特例もいっさい考慮していません。
一応、codeの意味やそれぞれどんな時に呼ばれるかはMSDNで説明してあるので
それに従って文字列を解析し、きちんと一貫したルールで値を返してやればちゃんと動作するはずです。理論的には。

実際には、どのcodeに対してどういう値を返すのが正解かはっきりしないので
自力で完璧を目指すのはかなり無理があると思います。
せめてお手本になるコードでもあればいいのですが、なかなか見つかりませんね。


  2010-10-02 11:33:42  No: 39179

>torさん
近いのだと、これかなぁ
http://support.microsoft.com/kb/273139/ja
私には変換できる程のスキルはないので参考で。

>かんとくさん
torさんが書いているように、イベントが発生するのであれば
ルールを決めるのは仕様次第だと思います。


かんとく  2010-10-07 00:59:05  No: 39180

いろいろとご指導ありがとうございます。

かなり難しいです。

「どこが、どう分かりません」という質問もできないくらい分からないので、もう無理かな、と思います。

RichEditにかわる何かを探そうかな、と思います。

ありがとうございました。


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

※Google reCAPTCHA認証からCloudflare Turnstile認証へ変更しました。






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