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

解決


すなくじら  2005-11-02 00:19:45  No: 18370

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

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

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

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

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


にしの  2005-11-02 00:37:25  No: 18371

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

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


すなくじら  2005-11-02 01:09:01  No: 18372

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

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


GPL  2005-11-02 01:12:11  No: 18373

ちょっと話がそれますが御免なさい。
># 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-02 01:23:45  No: 18374

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

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


代替ね  2005-11-02 01:36:11  No: 18375

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


GPL  2005-11-02 01:41:53  No: 18376

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


ForD  2005-11-02 06:01:17  No: 18377

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


にしの  2005-11-02 07:14:35  No: 18378

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


GPL  2005-11-02 11:12:41  No: 18379

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 20:03:31  No: 18380

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

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


書式指定可能  2005-11-02 20:26:17  No: 18381

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


すなくじら  2005-11-02 20:43:35  No: 18382

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


すなくじら  2005-11-02 20:51:19  No: 18383

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


りおりお  2005-11-02 20:52:46  No: 18384

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

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

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

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


すなくじら  2005-11-02 21:09:26  No: 18385

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


にしの  2005-11-02 21:29:48  No: 18386

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

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


すなくじら  2005-11-02 21:39:37  No: 18387

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

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

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

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

\begin
{

}

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


すなくじら  2005-11-02 21:54:17  No: 18388

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


あの  2005-11-02 22:45:51  No: 18389

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


masayan  2005-11-03 01:39:41  No: 18390

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

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-04 05:24:00  No: 18391

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

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


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








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