Memoに特定の文字を入力されたとき、その入力文字だけの文字色を変えるには?

解決


すなくじら  2005-11-01 15:19:45  No: 18370  IP: 192.*.*.*

Memoに文字を入力して、例えば『\begin』という文字列が入力された場合、
文字色を変えたいのですが、すべての文字列が入力されてから、
文字列の色が変わるのではなく、『\』の文字が入力された時に
文字色を変えて、最後の『n』が入力されたら、また文字色が
黒に戻るという形にしたいのですが。
途中、違う文字が入ったら文字色が黒に戻り、消して正しい文字に
書き直したら文字色がまた赤に変わるといった感じで。

-------------------------------------------------------------------
(例)\beginのとき文字色が赤に変わる場合

\←文字色が赤色に変化
b←赤のまま
e←赤のまま
g←赤のまま
o←スペルが違うので、文字色が黒に戻る
n←すでに間違っているので黒のまま

途中、『o』を消して、『n』に書き直すとまた、文字色が赤になる。

-----------------------------------------------------------------
よろしくお願いします。

編集 削除
にしの  2005-11-01 15:37:25  No: 18371  IP: 192.*.*.*

Memoの全体の文字色を変える、ということでしょうか。
KeyPressかSelChangeのたびに、SelStartより前の\を探して、そこからbeginという綴りがあっているか調べ、会っていたらFont.Color := clRedとすれば出来ます。

Memoの、\beginだけ赤にしたいのであれば無理です。
TEditorやTSynEditを使いましょう。
# TEditorはシェアウェア、TSynEditは未確認です(GPLだったかLGPLだったか)。

編集 削除
すなくじら  2005-11-01 16:09:01  No: 18372  IP: 192.*.*.*

Memoに入力した\beginだけの文字色を変えたかったので、無理ですか…。

例えば、こーゆのは無理ですか?
KeyPressなどで、\が押されたとき次のキー入力をbであるかどうかを
判定するのは不可能ですか?

編集 削除
GPL  2005-11-01 16:12:11  No: 18373  IP: 192.*.*.*

ちょっと話がそれますが御免なさい。
># TEditorはシェアウェア、TSynEditは未確認です(GPLだったかLGPLだったか)。
TSynEditがお勧めではありますが、にしのさんのご指摘のライセンスを今更ながら確認してみました。
SourceForgeのSynEditおページにはGPL,LGPL,MPLとなっていました。
複数のライセンスですか・・・(GPLとは思ってなかった^^;)
ソースコードなどのドキュメントを見るとLGPLとなっているものは見つかりませんでした。GPL2 or MPLとなっていました。
プロプライエタリなソフトに組み込むには考慮が必要そうですね。ふむふむ
ちなみに私は TMS softwareの TAdvMemo(有料)を利用してます。
http://www.tmssoftware.com/default.htm

編集 削除
すなくじら  2005-11-01 16:23:45  No: 18374  IP: 192.*.*.*

いえいえ、情報ありがとうございます。

あの、少し前からDelphi2005を使ってエディタを作成してるんですが、
ユーザ側からの視点からで、実現できそうな機能ってないでしょうか?
こんな質問ですみません。。。
先ほどの質問は、プログラミングの単語を入力した時のスペルが
あってる時だけ、色を変えるというスペルチェックの機能を
作成しようと思って質問してみたんですが。

編集 削除
代替ね  2005-11-01 16:36:11  No: 18375  IP: 192.*.*.*

>Memoに入力した\beginだけの文字色を変えたかったので、無理ですか…。
部分的に文字色を変えたいのなら RichEditを使いましょ。

編集 削除
GPL  2005-11-01 16:41:53  No: 18376  IP: 192.*.*.*

エディタって自作するとなると結構大変ですよね。
それで私は製品版を使用しているのですが TMSのTAdvMemoにはスペルチェックの機能もついています。(別に宣伝してるわけではありません)

編集 削除
ForD  2005-11-01 21:01:17  No: 18377  IP: 192.*.*.*

TAdvMemo、SynEdit などの海外製エディターコンポーネントって、
日本語入力時におかしく(変換動作がインライン上で行われない、文字化け)なりませんか?
どこか設定するところがあるのでしょうか。

編集 削除
にしの  2005-11-01 22:14:35  No: 18378  IP: 192.*.*.*

キャレット移動時に、ImmSetCompositionWindowで正しい位置に移動してやればOKです。
現在のSynEditでは、TCustomSynEdit.UpdateCaretでやっているようです。
# 私の環境のSynEditは少し古いのですが、たぶん入っているはず

編集 削除
GPL  2005-11-02 02:12:41  No: 18379  IP: 192.*.*.*

ForDさんwrote
>日本語入力時におかしく(変換動作がインライン上で行われない、文字化け)なりませんか?

にしのさんwrote
>キャレット移動時に、ImmSetCompositionWindowで正しい位置に移動してやればOKです。

今まで全く気にしていませんでした。^^;)
(そんなもんだと・・・)

SynEditも使用していますので SourceForge最新版2.0.2bで確認してみました。
にしのさんの仰る通り問題ありませんでした。
http://synedit.sourceforge.net/

Unicode版SynEditはForDさんご指摘の通りでしたが私はSynEditのMBCS版を使用していますのでこちらは保留・・・
http://mh-nexus.de/unisynedit.htm

TAdvMemoもForDさんご指摘の様に違う場所に表示されていました(文字化けはなし)のでSynEditを参考にImmSetCompositionFontとImmSetCompositionWindowの処理を追加して正常になりました。
ありがとうございました。

すなくじらさん、また横道にそれてすいませんでした。

編集 削除
すなくじら  2005-11-02 11:03:31  No: 18380  IP: 192.*.*.*

>部分的に文字色を変えたいのなら RichEditを使いましょ。

と、あったのですが、RichEditは、TMemoとは何が違うのでしょうか?
すみません、まだ全然わかってないことが多くて。。。
あと、どのような感じにすれば実現できるか、ヒント頂けないですか?

編集 削除
書式指定可能  2005-11-02 11:26:17  No: 18381  IP: 192.*.*.*

TRichEditは、TMemoとは違って文字の色、大きさ、太字、下線などを設定出来るコントロールです。一般のエディタはこのRichEditコントロールから派生するものが多いでしょう。

編集 削除
すなくじら  2005-11-02 11:43:35  No: 18382  IP: 192.*.*.*

そーなんですか!!勉強になりました。
ちなみにTMemoと比較して、機能を失ってる部分は、特にないのでしょうか?
あと、TMemoでも文字色を変える事だけなら出来たのですが、
文字色を変える点でどのように違うのですか?
すみませんが、なるべく詳しく教えていただけないでしょうか?

編集 削除
すなくじら  2005-11-02 11:51:19  No: 18383  IP: 192.*.*.*

すごく基本的な質問になるですけど、
TRichEditで実行したときに、中にRichEdit1と表示されたまま
実行されるのですが、これを消して実行するにはどーすれば
よいのでしょうか?
ちなみに、TEditにはcaptionっていう欄があって簡単に消せたのですが、
TMemoやTRichEditにはなくて…。

編集 削除
りおりお  2005-11-02 11:52:46  No: 18384  IP: 192.*.*.*

>一般のエディタはこのRichEditコントロールから派生するものが多いでしょう。

そんなことはないです。自前のエディットコントロールか TEditor のような
Windows ネイティブのコントロールでないのが一般のエディタです。

今回の質問の意図は、いわゆる「Syntax Highlighting and code completion」
に属することなので、特定部分のフォントや色を変えられるだけでは、解決しません。

SyEdit や TEditor などの既存のものを使うか、もしくは非常に高度になりますが
自分でコントロールを作るしかないと思います。

編集 削除
すなくじら  2005-11-02 12:09:26  No: 18385  IP: 192.*.*.*

既存のものですか。。。
確かに僕も個人としては、既存のエディタを使用することに
大賛成なのですが、個人の事情でエディタの研究を迫られてて、
何かしら機能を追加しないといけなくて。。。
だから、自分のわずかな力量ぐらいで出来る機能のはないか、
いろいろプログラムを考えては試してる感じです。
ホント申し訳ないです…<(_ _)>

編集 削除
にしの  2005-11-02 12:29:48  No: 18386  IP: 192.*.*.*

時間がなく、適当な機能を搭載したい、というのであれば、テンプレート機能などが簡単です。
たとえば、
${now}と書かれた部分を、変換ボタンで現在時刻に置き換えるとか。
エディタの機能というより、付加機能ですが。

それと、1からエディタを作る上で重宝する資料が、ViVi作者さんのところにあります。
http://hp.vector.co.jp/authors/VA007799/vivi.htm
# Delphiではありません

編集 削除
すなくじら  2005-11-02 12:39:37  No: 18387  IP: 192.*.*.*

何度も質問をすみません。

ちなみにこーゆう事は実現可能でしょうか?

短縮コマンドを作成して、『\begin』と入力したら、

-------------------------------------------------

\begin
{


}

-------------------------------------------------
と、表示させることはなんとか出来たのですが、
カーソルを{}の中の行にもっていくことは出来るんでしょうか?
Memo1.SelStartって形で試してみて、カーソル位置が指定できる事は
わかったのですが、この場合Memo1の中の位置を指定するだけみたいで、
1行目で実行した場合で設定すると、違う行で短縮コマンドを実行した場合、
関係ないところにカーソルがありました(涙)
Memo内の真ん中で短縮コマンドを利用したときにも同様に、
{}の中にカーソルを持っていく方法はないでしょうか?

編集 削除
すなくじら  2005-11-02 12:54:17  No: 18388  IP: 192.*.*.*

にしのサン、貴重な意見ありがとーございます(*^v^*)
参考にさせていただきます!!
あの、LaTeXの為のエディタを作成しているので、
実際に使用するときにあれば便利だな〜と思われる機能を実装させたくて。

編集 削除
あの  2005-11-02 13:45:51  No: 18389  IP: 192.*.*.*

もう標題と関係のない質問内容になっているようですから、
適切な標題の別にスレッドを立てて、続けたらどうでしょうか。

編集 削除
masayan  2005-11-02 16:39:41  No: 18390  IP: 192.*.*.*

不完全ですが、こんな感じでどうでしょう?

type
  TForm1 = class(TForm)
    RichEdit1: TRichEdit;
    procedure RichEdit1KeyPress(Sender: TObject; var Key: Char);
    procedure RichEdit1Change(Sender: TObject);
    procedure FormCreate(Sender: TObject);
  private
    { Private 宣言 }
    FCheckLineNo : Integer;
  public
    { Public 宣言 }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  FCheckLineNo := -1;
  RichEdit1.Lines.Clear;
end;

procedure TForm1.RichEdit1KeyPress(Sender: TObject; var Key: Char);
var
  LineNo,CP : Integer;
  buf : String;
begin
  // カーソルのある行番号とその行の先頭文字位置を取得
  LineNo := SendMessage(RichEdit1.Handle,EM_LINEFROMCHAR,-1,0);
  CP     := SendMessage(RichEdit1.Handle,EM_LINEINDEX,LineNo,0);

  // OnChangeでのスペルチェック行を設定
  FCheckLineNo := LineNo;

  // カーソル行先頭からカーソル位置までの文字+今入力された文字を取得
  buf := Copy(RichEdit1.Text,CP + 1,RichEdit1.SelStart - CP) + Key;

  // 後ろが'\begin'であれば...
  if AnsiEndsStr('\begin',buf) then
  begin
    // 今入力された文字と'{ }'行を挿入
    RichEdit1.SelText := Key;
    RichEdit1.SelText := #13#10 + '{' + #13#10 + #13#10 + '}' + #13#10;
    // カーソル位置を '{}'の間に移動
    RichEdit1.SelStart := CP + Length(buf) + 5;
    Key := #0;
  end;

end;

procedure TForm1.RichEdit1Change(Sender: TObject);
var
  CP,P,SL : Integer;
  OldSelStart : Integer;
  buf : String;
begin
  // スペルチェックする行が無効であれば、何もしない。
  if (FCheckLineNo < 0) or (FCheckLineNo >= RichEdit1.Lines.Count) then exit;

  // チェックする行の文字列を取得
  CP     := SendMessage(RichEdit1.Handle,EM_LINEINDEX,FCheckLineNo,0);
  buf := RichEdit1.Lines[FCheckLineNo];

  FCheckLineNo := -1;

  // 現在のカーソル位置を保存
  OldSelStart := RichEdit1.SelStart;

  // 行の文字色を標準にする
  RichEdit1.SelStart := CP;
  RichEdit1.SelLength := Length(buf);
  RichEdit1.SelAttributes.Color := RichEdit1.Font.Color;

  // 最初の'\'で始まる文字位置を取得する
  P := PosEx('\',buf);
  while P > 0 do
  begin
    if not AnsiStartsStr('\begin',Copy(buf,P,Length(buf) - (P - 1))) then
    begin
      // '\begin'以外であればその部分の色を赤にする。
      RichEdit1.SelStart := CP + (P - 1);
      // 赤にする範囲は、スペースまたは行の最後まで
      SL := PosEx(' ',buf,P) - P;
      if SL <= 0 then
        SL := Length(buf) - (P - 1);
      RichEdit1.SelLength := SL;
      RichEdit1.SelAttributes.Color := clRed;
    end;

    // 次の'$'文字位置を取得する
    P := PosEx('\',buf,P + 1);
  end;

  // カーソル位置を元に戻す
  RichEdit1.SelStart := OldSelStart;
end;

end.

編集 削除
すなくじら  2005-11-03 20:24:00  No: 18391  IP: 192.*.*.*

masayanサン、わざわざプログラムまで書いて頂き
ありがとうございます!!
試してみますね!!
これで大分はかどると思います。

そして、質問の内容からかなりずれてしまってすみませんでした。
次わからないことがあったら、また新しくスレッドを建てさせて
頂きますね。
どーもありがとうございました。

編集 削除