初心者です。どうか宜しくお願い致します。
リッチエディットでテキストエディタの作成に挑戦しています。
メモ帳の様に、現在のカーソルの位置の行番号と列番号をステータスバーに表示したいのですがどうすればよいか解りません。教えていただけないでしょうか。
余談ですがエディタを作るならフリーの高機能なコンポを使ったほうがいいですよ
ApplicationEvents1 を置いてその OnIdle イベントハンドラを以下のようにします。
procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
var Done: Boolean);
var
Line,CharNo:integer;
begin
with RichEdit1 do begin
Line := SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
CharNo := SendMessage(Handle,EM_LINEINDEX,Line,0);
StatusBar1.SimpleText := Format(' %.4d 行 %.4d 列',
[Line+1,SelStart-CharNo+1]);
end;
end;
無駄なコードを実行しないように、少し改良しました。
type
TForm1 = class(TForm)
StatusBar1: TStatusBar;
RichEdit1: TRichEdit;
ApplicationEvents1: TApplicationEvents;
procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
revSelStart:integer; // 手動で追加する
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
var Done: Boolean);
var
Line,CharNo:integer;
begin
if revSelStart <> RichEdit1.SelStart then
with RichEdit1 do begin
revSelStart := SelStart;
Line := SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
CharNo := SendMessage(Handle,EM_LINEINDEX,Line,0);
StatusBar1.Panels[0].Text := Format(' %.4d 行 %.4d 列',
[Line+1,SelStart-CharNo+1]);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
revSelStart := -1;
end;
_さん、jokさんありがとうございます。
jokさん、コードまで書いていただきありがとうございます。
revSelStartを設けたのはどういうことなのでしょうか?
>revSelStartを設けたのはどういうことなのでしょうか?
試しにメンバー変数IdleCnt追加して、こないコードでマウス動かして
revSelStart変数あるなしの違い実感してや。
........
inc(IdleCnt);
StatusBar1.Panels[0].Text := Format(' %.4d 行 %.4d 列 Cnt=%d',
[Line+1, SelStart-CharNo+1, IdleCnt]);
end;
> revSelStartを設けたのはどういうことなのでしょうか?
詳しく説明するわけにはいかないのですが、Application.OnIdle イベントは
かなり頻繁に起こります。そのたびに表示を更新するのは無駄だと思いますので、
revSelStart に前回のキャレット位置を保存しておき、キャレット位置に変化が
あったときだけ、表示を更新するようにしているわけです。Muda? さんの指摘通り
のコードを実行してみると違いが分かりると思います。
Muda?さんのコードを実行してみました。
どちらもずっとCnt=1のままで違いがわかりません。
みえないところでかかる負担を少なくしているわけです
> どちらもずっとCnt=1のままで違いがわかりません。
これは
> 試しにメンバー変数IdleCnt追加して、
をしてなくて、ローカル変数にしてるんじゃないですか?
> キャレット位置に変化があったときだけ
の条件は、コードの中の
if revSelStart <> RichEdit1.SelStart then
の部分で判断しています。この判断をする前とした後でどのくらい回数が違うか
を見るといいのです。以下のようにします。
type
TForm1 = class(TForm)
StatusBar1: TStatusBar;
RichEdit1: TRichEdit;
ApplicationEvents1: TApplicationEvents;
procedure ApplicationEvents1Idle(Sender: TObject; var Done: Boolean);
procedure FormCreate(Sender: TObject);
private
{ Private 宣言 }
public
revSelStart:integer; // 手動で追加する
IdleCnt1,IdleCnt2:integer; // これらも手動で追加する
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.ApplicationEvents1Idle(Sender: TObject;
var Done: Boolean);
var
Line,CharNo:integer;
begin
inc(IdleCnt1);
if revSelStart <> RichEdit1.SelStart then
with RichEdit1 do begin
revSelStart := SelStart;
Line := SendMessage(Handle,EM_LINEFROMCHAR,SelStart,0);
CharNo := SendMessage(Handle,EM_LINEINDEX,Line,0);
Inc(IdleCnt2);
StatusBar1.Panels[0].Text := Format(' %.4d 行 %.4d 列 OutIf: %d InIf: %d',
[Line+1,SelStart-CharNo+1,IdleCnt1,IdleCnt2]);
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
revSelStart := -1;
end;
これで、OutIf の回数が InIf の回数よりかなり多いことが分かるでしょう。
ローカルにしてました…
たいへんお手数をおかけ致しました。
有り難う御座いました。
ツイート | ![]() |