初めまして。早速ですが質問に入らせていただきます。
Delphi初心者ながら、チャットクライアントを作りました。
というか途上です(いつかChanpionに:もっと上を目指したいです)
ログの表示にはRichEditを使っているのですが、タグに対応させた為か
一度に複数行(二桁)表示された場合、ちらつきが非常に気になります。
現在はSelAttributesで色・フォント・サイズ・書式を変更しています。
(現実には複数行表示ではなくて、複数人同時・連続発言⇒連続表示ですが)
色々探し回ってみましたが、ちらつきはImageに関するものばかりでした。
何かいい手段がありましたら、ご教授お願いします。<(。。)>
内容の更新を
RichEdit1.Lines.BeginUpdate;
try
{ 内容の更新 }
finally
RichEdit1.Lines.EndUpdate;
end;
としても改善されませんか?
素早いレス、ありがとうございます。
BeginUpdate/EndUpdate は、すでにやっておりまして、
一旦BkColor(白にしています)で塗り潰される事による
ちらつきを抑え込みたいのです(非常に目に悪そうです)
スムーズなスクロールをさせているアプリケーションを
見掛けますが、APIを駆使しないと無理なんでしょうか…?
具体的にどんな処理なのか文章だけではイメージが湧かないのですが、
とりあえずRichEditのDoubleBufferedプロパティをTrueにしてみては?
もしかしたらもう試していますか?
気付いた事が一つ。ログ表示処理のあと BeginUpdate の前に
if RichEdit.Perform(EM_LINEFROMCHAR, -1, 0) > 100 then
for i := 1 to 30 do RichEdit.Lines.Delete(0);
で、最大表示行数を制限しているのですが、無関係でしょうか。
駄目でした。RichEdit.DoubleBuffered := True; にすると、
何故かログの表示が真っ白になります。
> 気付いた事が一つ。ログ表示処理のあと BeginUpdate の前に
> if RichEdit.Perform(EM_LINEFROMCHAR, -1, 0) > 100 then
> for i := 1 to 30 do RichEdit.Lines.Delete(0);
> で、最大表示行数を制限しているのですが、無関係でしょうか。
BeginUpdateの前で、ということですから、ちらつくでしょうね。
EndUpdte の間違いでした。少々長いですが、ソースを書きます。
with (RichEdit As TRichEdit) do begin
Lines.BeginUpdate;
try
Lines.Add(WORD);
OLDPos := SelStart - Length(WORD) - 2;
END := SelStart;
for i := 0 to 3 do while TAGLIST[i] <> '' do begin
TAGSTART := StrToInt(Copy(TAGLIST[i], 1, AnsiPos('*/', TAGLIST[i]) - 1));
Delete(TAGLIST[i], 1, AnsiPos('*/', TAGLIST[i]) + 1);
TAGPROV[i] := Copy(TAGLIST[i], 1, AnsiPos('*/', TAGLIST[i]) - 1);
Delete(TAGLIST[i],1,AnsiPos('*/',TAGLIST[i]) + 1);
SelStart := OLDPosition - 1 + TAGSTART;
SelLength := END - SelStart;
if TAGPROV[i] <> '' then case i of
0: SelAttributes.Color := ColorType[AnsiIndexText(TAGPROV[0], ColorTAG)];
1: SelAttributes.Size := SizeType[AnsiIndexText(TAGPROV[1], SizeTAG)];
2: SelAttributes.Style := StyleType[AnsiIndexText(TAGPROV[2], StyleTAG)];
3: SelAttributes.Name := TAGPROV[3];
end;
TAGPROV[i] := '';
end;
if Perform(EM_LINEFROMCHAR, -1, 0) > 150 then
for i := 1 to 30 do Lines.Delete(0);
SelStart := END;
finally
Lines.EndUpdate;
end;
end;
TAGLIST[i]にはタグ抽出ルーチンでタグ位置+'*/'+タグ(省略型)+'*/'を交互に入れています。
ここ(実描画ルーチン)ではタグ位置と、TAGPROV[i]にタグを1つづつ取り出して、
省略タグの配列を検索、その数字を実際の SelAttributes の配列に入れて変換しています。
{ と } で処理のまとまりごとにコメント化してみて問題箇所を特定してみるのはどうですか?
原始的な方法ですが、結構効果があります。
あと、これ
http://www2.big.or.jp/~osamu/Delphi/Tips/key.cgi?key=33#0216.txt
少しでも問題解決のヒントになりませんか?
そのHPも参考にさせて頂きましたが、最初に書いたとおり私は Delphi を触り始めて
まだ三ヶ月と日が浅く勉強不足で、APIで書かれたソースは半分も理解できません。
ちょっと質問の意味がちゃんと伝わっていなかったようなので、改めて書かせてもらいます。
RichEditに文字を高速に描画させるのではなく、連続で書き込んだ時のスクロール時の
ちらつきを消したいのです。やりたい事の簡潔なソースを書きます。
FormにRichEditとButtonを配置して、RichEditのHideSelectionをFalseに。
procedure TForm1.Button1Click(Sender: TObject);
var
i,ENDPOS: Integer;
begin
for i := 0 to 20 do
with (RichEdit1 As TRichEdit) do
begin
Lines.BeginUpdate;
try
Lines.Add('Delphi Q & A 掲示板');
ENDPOS := SelStart;
SelStart := SelStart - 14;
SelLength := 5;
SelAttributes.Color := clRed;
SelStart := ENDPOS;
finally
Lines.EndUpdate;
end;
end;
end;
ボタンを押すと文字が流れて、再描画の為に逐一塗り潰している為なのかちらつきが出ます。
このちらつきを消して、スムーズにスクロールさせたいのです。
一旦ログを貯めこんで一気に描画を。とも考えましたが、連続で次のログが来ると駄目でした。
ここでなら解決できそうに思えてこちらに書きました。
Delphi先駆者の皆様方、改めてよろしくお願いします。
これだと、1回のループごとにBeginUpdate, EndUpdateすることになるので、ちらつきますよね。
編集 削除にしのさんが書いていらっしゃる通りで、for i := 0 to 20 do のループの中で
BeginUpdate〜EndUpdate を繰り返してしまうと、BeginUpdate〜EndUpdateの意味が
全くなくなってしまいます。
それにしても、挑戦者さんの最初の質問からはこういうことは想像できませんでした。(汗)
挑戦者さん、ちらつきは改善されましたか?
編集 削除この方法では駄目だという事でしょうか?APIを駆使しなければ無理なのか、
又は他のコンポーネント(例えばSonEdit??)使えば解決できるのでしょうか?
チャットソフトの性格上、連続して届いたログは連続して表示したいのです。
ちなみにBeginUpdate〜EndUpdateを使わず処理すると、黒いちらつきが入るばかりか、
複数の表示色/フォント/サイズ変更等などがあると、とんでもなく遅くなったりします。
> この方法では駄目だという事でしょうか?
私の最初のレスと同じことなのですが、
procedure TForm1.Button1Click(Sender: TObject);
var
i, ENDPOS: Integer;
begin
with RichEdit1 do
begin
Lines.BeginUpdate;
try
for i := 0 to 20 do
begin
{ 処理 }
end;
finally
Lines.EndUpdate;
end;
end;
end;
こういう風に書くべきではないでしょうか。
for文の内側に BeginUpdate〜EndUpdate が入っていると、
繰り返しの数だけ EndUpdate で更新されるはずです。
もし上記の方法でもちらつくようでしたら、このことは忘れてください。(苦笑)
いや、ちょっとこちらのやりたい事が伝わっていないようです(汗
チャットクライアントなので、基本的には発言を一行だけ処理します。
当然、表示は一行だけなのでちらつきはありません。(気にならないだけかも?)
ですが、複数人が同時に発言すると、ソケットが連続して受け取って
処理を回す為に一気にスクロールして、ちらつくのです。
タイミングにもよりますが、二行続いただけでも目立ちます。
わざわざループを作ってソースを書いたのは、分かり易くする為だったのですが、
かえって混乱させてしまって申し訳ありませんでした。
あと、ダミーのRichEditに一旦表示してからStream経由でコピーさせようと
試みましたが、失敗に終わりました・・・
挑戦者さんの発言とコードを見て私にわかることは書いたつもりですので、
あとは他の方からのレスを期待しましょう。
ふぐちゃんさん、質問に延々お付き合い下さってありがとうございます。
不可能とは思えないので今後も自分なりに色々と調べてやってみるつもりですが、
何かいい方法がありましたら、みなさんご教授お願いします。
素人考えで的外れかもしれませんが、OS⇔アプリケーションの間のやり取り
に何か細工できるのはないかと睨んでおります。
>チャットクライアントなので、基本的には発言を一行だけ処理します。
>当然、表示は一行だけなのでちらつきはありません。(気にならないだけかも?)
>ですが、複数人が同時に発言すると、ソケットが連続して受け取って
>処理を回す為に一気にスクロールして、ちらつくのです。
ならば発想を変えてみたらどうかにゃ〜?
◇RichEditに入れるのは実際に見える行だけ。見えない行を入れなければスクロールもなし。
◇受信文字列をTStringListなどに貯めて、表示する部分だけをTimerでRichEditに転送して、書式を変更。
◇書式の変更に時間がかかってチラツクのなら、文字列をあらかじめRTF形式に変換してからRichEditに転送。
流れる文字でしたらTipsがここにありますが、参考にならないでしょうか?
http://www.geocities.jp/lupin_home/delphi/index.html#1に
LupinⅢさんの紹介ページのTipsは、Imageに描画させてますね。
Imageで全て作り直すとすると、私の力にはとても・・・(汗
にゃ〜さんの
> 文字列をあらかじめRTF形式に変換してからRichEditに転送
が今の私にできそうな有効な手段のようです。
とりあえず、RTF方式での転送がうまくいくかどうか頑張ってみます。
色々と試行錯誤してみて、最終的に文字列を貯めて、
尚且つバックカラーをちらつきが目立たない色にするという
消極的戦法(笑)で一応の解決を図りました。
お答えを下さったみなさん、ありがとうございました。