[リストへもどる]   [VBレスキュー(花ちゃん)]
一括表示

投稿時間:2005/03/24(Thu) 00:02
投稿者名:kuro3
Eメール:
URL :
タイトル:
「解決済み」リッチテキストボックスを用いたターミナル パートU
★2005/03/26追記★
皆様のご支援の結果、問題解決できました。本当にありがとうございます。
(おかげさまで、最低必要条件を満たすコードはついさっき完成しました。)
いつか、逆に自分が支援できるように精進させていだきます。
★2005/03/26追記はここまで★

kuro3といいます。
多くの方の返信、本当にありがとうございます。
また、夜しか返信できておらず申し訳ございません。仕事の都合で・・・。
スレッドが長くなりましたので、パート2を作成させていただきました。

実は、リッチテキストボックスを使用しまして、
ターミナル関係のアプリを作り初めているのですが、障害にあたってしまいました。
できましたら知恵をお貸しいただけないでしょうか。

1)やりたいこと
  リッチテキストボックスの文字列が、501行以上になったら、
  下から500行を残して文字列を削除すること。

2)いま問題となっていること。
  ・処理が遅すぎる。
   受信文字が、すごい勢いで増えており文字列削除のスピードが
   間に合わなくなってしまいました。
  ・画面がちらつく

3)具体的処理内容
  0.タイマー処理にて受信した文字をリッチテキストボックスに追記
    (seltextにて行っております。)
  @.こちらのHPにて紹介されております行数取得の手法にて、
    リッチテキストボックス全体の行数を削除
  A.(全体の行数-500行)にて削る必要のある行数をチェック
  B.リッチテキストボックスの先頭から、削る必要がある分だけ、
    instrを用い改行コードの位置を検索
  C.Bで検索した改行コードの位置をもとにRightコマンドで、
    500行分の文字列を作成
  D.Cで作った文字列をリッチテキストボックスに貼り付け


処理がおそいのは、3−B,Dあたりでもたついていると考えているのですが、
画面がちらつくほうはなにがなにやらと言った状況です・・・。


また、下記が本ターミナルの基本思想となっております。

テキスト表示系
・文字単位でのコピーを行うこと。
 (3行目の5文字目から、6行目の3文字目など)
・文字を色分けできること。
・文字は、半角/全角混じりです。

ターミナルとして、絶対やりたいこと。
・500行程度のログをちらつきなしで、表示したい。
 (目視したい)
・多少ちらついても、1万行オーバーのログをとりたい。
・ログは上から下にながし、
 受信文字の最終行を、一番したに表示すること。
 

送受信環境(参考です)
・受信文字列は、半角のみ。
・送信文字列は、全角あり。(使用頻度小)
・送信文字の改行コード間の文字数は、
 0〜無制限(実際は、0〜100文字程度です。)
・受信文字は、1秒で400行程度更新されております。
 もっと、あがる可能性はありますが・・・。

OSなど
・win2k pro + vb6

アドバイスいただけましたら幸いです。

投稿時間:2005/03/24(Thu) 00:10
投稿者名:kuro3
Eメール:
URL :
タイトル:
先ほどのスレッドでの解答残しにつきまして
花ちゃんさんへ
ガッさんへ

kuro3です。
先スレッドの残解答ということで、
失礼ながら、ひとつのレスでの返信お許しください。


花ちゃんさんへ

>どこが違うのでしょうかね。私の環境ではスクロールバーは動きません。
そうなのですか!?、こちらでは
RichTextBox1.Text = "あ"
とするだけで、カレットは一番最初に動いてしまいます。
すこし、この方向をしらべてみたいと思います。
>とりあえず、レスが長くなり見づらくなったので パートU と言う事で
>新しいスレッドで質問するようにして下さい。。
了解です。

ガッさんへ
返信ありがとうございます。

ずばり、文字単位でコピーと文字の色ずけがしたいのです・・・。

投稿時間:2005/03/24(Thu) 00:51
投稿者名:kuro3
Eメール:
URL :
タイトル:
スクロールバーが動く理由につきまして
自己レス失礼いたします。

> 花ちゃんさんへ
>
> >どこが違うのでしょうかね。私の環境ではスクロールバーは動きません。
> そうなのですか!?、こちらでは
> RichTextBox1.Text = "あ"
> とするだけで、カレットは一番最初に動いてしまいます。
> すこし、この方向をしらべてみたいと思います。

スクロールバーの動く原因の予想がつきました。
理由はわからないのですが、下記コードを実行する際に、
RichTextBox1にフォーカスがある際は、スクロールバーが上下に動き、
その他のコントロールにフォーカスがある場合は、
一番したに固定するようです。

'前処理
'RichTextBox1.ScrollBars を 3に設定願います。
Private Sub Form_Load()

   'リッチテキストに複数行をデータを用意しておく。
   RichTextBox1.Text = "hjkljfajslkfjal" + vbCrLf + _
   "hjkljfajslkfjal" + vbCrLf + "hjkljfajslkfjal" + vbCrLf + "hjk
ljfajslkfjal" + vbCrLf + _
     〜中略〜 スクロールバーが出る程度の行数設定をお願いいたします。
   "hjkljfajslkfjal" + vbCrLf   


End Sub

Private Sub Timer1_Timer()
    Dim n As Long
    RichTextBox1.SelStart = 2147483647
    '現在の文字数を取得
    n = Len(RichTextBox1.Text)
    '現在の文字列を現在の文字列+追加書き込みした文字数で置き換える
    RichTextBox1.Text = Right$(RichTextBox1.Text & "あ" + vbCrLf, n)  
    RichTextBox1.SelStart = 2147483647
    '現在の文字数を取得
    n = Len(RichTextBox1.Text)
    '現在の文字列を現在の文字列+追加書き込みした文字数で置き換える
    RichTextBox1.Text = Right$(RichTextBox1.Text & "しくしくしく" + vbCrLf, n)

End Sub

投稿時間:2005/03/24(Thu) 08:11
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re: スクロールバーが動く理由につきまして
> スクロールバーの動く原因の予想がつきました。
> 理由はわからないのですが、下記コードを実行する際に、
> RichTextBox1にフォーカスがある際は、スクロールバーが上下に動き、
> その他のコントロールにフォーカスがある場合は、
> 一番したに固定するようです。

確認しました。
受信データがあった場合は、ダミーのコントロールにフォーカスを移す事で解決
出来るかと思います。

IF 受信データ="" Then Exit Sub
  ダミーのコントロール.SetFocus
のような一文をいれれば。

どうしても行による管理が必要なら、まだ試してはいませんが、API関数を使って
1行目の文字列を "" で置き換えて見ればひょっとして使えるかも知れません。
今の文字数で置き換える方法で500行を実行して取りこぼしや速度的に問題がないかを
試して頂けませんか? 500行で問題がなければ、どれ位の行数までなら許される処理速度か
試して見て下さい。(1000行までなら OK とか)

500行もだめなら、今の条件では無理かも知れません。(ある程度どこかで妥協しないと)

勿論、現在は文字数で管理しているのでおおよその文字数を行数に置き換えた数字で
いいのですが。

投稿時間:2005/03/24(Thu) 11:17
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
リッチテキスト パートU(無理じゃないでしょうか)
>・受信文字は、1秒で400行程度更新されております。
> もっと、あがる可能性はありますが・・・。

私のPCでは不可能です。
下記で500行表示するのに7.8秒かかります。

Private Sub Timer1_Timer()
    N1 = N1 + 1
    RichTextBox1.Text = RichTextBox1.Text & N1 & vbCrLf
End Sub

置き換え処理をしていても7.8秒掛かっていたので上記のような一番シンプルなコードで
試しても7.8秒と変わらないのでマシンの方での限界かと思います。
従ってどのようなコードを書いても1秒間に64行程度しか更新できません。

ちなみに、テキストボックスで試しても同じタイムでした。

Private Sub Command1_Click()
    While N1 < 500
        N1 = N1 + 1
        RichTextBox1.Text = RichTextBox1.Text & N1 & vbCrLf    '1.1秒
      '  Text1.Text = Text1.Text & N1 & vbCrLf   ' 1.7 秒
    Wend
End Sub
これならなんとか受信だけならできそうですが。



WindowsXP(HE SP2) Pentium 4  1.70GHz  640MB RAM  VB6.0(SP6)

投稿時間:2005/03/25(Fri) 02:04
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re: リッチテキスト パートU(無理じゃないでしょうか)
返信まえに2回もの返信ありがとうございます。
次にいただいた返信の内容理解後、改めて返信させていただきたいと
思いますが、ちょっと脳みそパンクするレベルの内容でしたので、
申し訳ありませんが、少し時間をください。

自分で、作成中のコードにマージ中なのですが、いまの私のレベルでは難航中です。
どんなに、遅くても明日の晩にはなんらからの結果を書き込みさせていただくように
努力しますので、ご容赦お願いいたします。

投稿時間:2005/03/25(Fri) 07:40
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^2: リッチテキスト パートU(無理じゃないでしょうか)
> 自分で、作成中のコードにマージ中なのですが、いまの私のレベルでは難航中です。

'------- 先頭行1行削除 ------------  の部分だけ使って試してもらえばいいかと
思います。
受信データの表示は今まで通りの追加書き込み
RichTextBox1.Text = RichTextBox1.Text & 受信データ
    If SendMessage(RichTextBox1.hwnd, EM_GETLINECOUNT, 0&, 0&) > 501 Then

      途中 省略

    End If
といった形で取り合えずどうなるか試して頂き?
処理が遅いようなら表示の部分を置き換え処理にするか、ある程度の受信文字数に
なった時点で追加書き込みする等工夫すればいいかと思います。
この ----- 先頭行1行削除 ------ の処理は、API関数で先頭行の文字数を取得して
””(空白)で置き換え(削除)しており処理速度は計測出来ない程早いのでまず削除
遅れにならないかと思いますが、一度に2〜3行削除する事も簡単です。

  

投稿時間:2005/03/24(Thu) 12:38
投稿者名:魔界の仮面弁士
Eメール:
URL :
タイトル:
Re: リッチテキストボックスを用いたターミナル パートU
リッチテキストボックスでは無理じゃないですかね。

文字入力可能なコントロールで無くても良いなら、
ListBoxにカスタムドローしてみるとか。

文字単位の色付けではなく、行単位の色付けでよければ、
TreeViewコントロールを使ってみるとか。

色付け自体を省略しても良いなら、DBGridのUnboundモードを使うとか。

件数が多すぎて、コントロール側では扱いきれないようであれば、
ログをPictureBoxに自前で描画して、スクロールを別途実装するとか。

投稿時間:2005/03/25(Fri) 01:40
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re^2: リッチテキストボックスを用いたターミナル パートU
魔界の仮面弁士さんへ
返信ありがとうございます。

> 文字単位の色付けではなく、行単位の色付けでよければ、
> TreeViewコントロールを使ってみるとか。
>
> 色付け自体を省略しても良いなら、DBGridのUnboundモードを使うとか。
残念なのですが、文字単位の色付けを必須と考えております。
色づけ手段は確かに、どんな手段でも問題ないのですが、
ログをピクチャに転写するとより処理に時間がかかってしまうのです。
(現状の私の知識レベルでは。)

投稿時間:2005/03/24(Thu) 13:32
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re: リッチテキストボックスを用いたターミナル パートU
人間が目で追えるのは、1秒間ではせいぜい数行です。
ですから、そのような形で逐次追う必要はないのではないか、
と思います。

まず、ログをきちんと出力すること、そして、それを後から
チェックしやすくするUIを構築すること、の2段階で考える
べきではないでしょうか。

投稿時間:2005/03/25(Fri) 01:55
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re^2: リッチテキストボックスを用いたターミナル パートU
K.J.Kさんへ

> 人間が目で追えるのは、1秒間ではせいぜい数行です。
> ですから、そのような形で逐次追う必要はないのではないか、
> と思います。

揚げ足とりのようで、恐縮なのですが・・・。
嫌な勢いでながれるログから、必要なログが帰ってきた瞬間のみ
キーを殴るようなひどい状況に置かれてしまい、すこしでも幸せになりたく、
今回、このプログラムを組み始めました・・・。
(ちょっと、愚痴になって申し訳ないです。
 実は、ちょっと工夫をすることと、多くのかたが助けてくれる
 現状に少し、いや、結構の幸せを感じている今日、昨今なんです。) 

投稿時間:2005/03/25(Fri) 08:39
投稿者名:K.J.K.
Eメール:akiya@koalanet.ne.jp
URL :
タイトル:
Re^3: リッチテキストボックスを用いたターミナル パートU
> 揚げ足とりのようで、恐縮なのですが・・・。
> 嫌な勢いでながれるログから、必要なログが帰ってきた瞬間のみ

でしたら、直接ログを表示するのではなく、ログを受け取ったら
そこから必要なログを探し出して、もしあったときにはそれを
UIにて知らせる、という構造でいいのでは。

投稿時間:2005/03/25(Fri) 16:32
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re^4: リッチテキストボックスを用いたターミナル パートU
> でしたら、直接ログを表示するのではなく、ログを受け取ったら
> そこから必要なログを探し出して、もしあったときにはそれを
> UIにて知らせる、という構造でいいのでは。

そうですね。その機能も便利という印象を受けました。
ログ処理とは別に将来の実装はしてみたいです。

投稿時間:2005/03/24(Thu) 16:51
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
現在の条件では最速かも?
解決されたようなのでこのコードは削除させて頂き改めて
逆引きヘルプの方にアップしたいと思います。

投稿時間:2005/03/25(Fri) 17:03
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re: 現在の条件では最速かも?
アドバイスいただきましたとおり、まず試してみました。
結果、びっくりするくらい早くなりました。
ただ、一行づつでの削除では、まだ少々もたついておりましので、
500行を超えた分はまとめて、削除を行おうと思いまして、
下記部分を、
> N1 = SendMessage(.hwnd, EM_LINEINDEX, CLng(1), 0)
 N1 = SendMessage(.hwnd, EM_LINEINDEX, CLng(現在の表示行数 - 500), 0) 'まずは500行
のように書き換えて試してみたのですが、このような変更の仕方でよいのでしょうか?
一応、結果を見てみると想定どうりに動いている感じなのですが・・・。
上記、変更の仕方が問題ないとすると、1万行程度では問題なくログがとれるようになりました。

また、APIの仕様をうまく調べることができなかったのですが、
提案していただいたコードの動きは、
@.行指定
A.指定行の最後までの文字数を選択
B.選択文字を、””と置き換え
と、いうステップで動いているという理解でよいのでしょうか?


> (1行の文字数が無制限のような行が受信されるなら否応無しに文字数で管理を
> せざるを得ないと思うのですが)
ご指摘を受けるまで、失念しておりました・・・。
確かに一行にメガオーダでデータ受信が発生すると洒落にならないコードにしてました。
行単位とは別に、文字数の管理も入れておこうとおこうと思います。

投稿時間:2005/03/25(Fri) 17:41
投稿者名:花ちゃん
Eメール:
URL :
タイトル:
Re^2: 現在の条件では最速かも?
> > N1 = SendMessage(.hwnd, EM_LINEINDEX, CLng(1), 0)
>  N1 = SendMessage(.hwnd, EM_LINEINDEX, CLng(現在の表示行数 - 500), 0) 'まずは500行
> のように書き換えて試してみたのですが、このような変更の仕方でよいのでしょうか?

CLng(1) で2行目の先頭までのバイト数(半角1バイト換算での)を取得しています。

Ret = SendMessage(.hwnd, EM_SETSEL, 0, ByVal N1)
で選択範囲を設定しています。[ 0, ByVal N1 ]0バイト目から2行目の先頭まで
を選択しております。

Ret = SendMessage(RichTextBox1.hwnd, EM_SETTEXTEX, VarPtr(SetTextPos), ByVal vbNullString)
上記で選択した範囲の文字列を vbNullString と リッチテキストフォーマットを保ったまま置換
しております。(置き換える場合は置き換える文字列を指定)

> 上記、変更の仕方が問題ないとすると、1万行程度では問題なくログがとれるようになりました。
それが心配でしたが、なによりです。

> 行単位とは別に、文字数の管理も入れておこうとおこうと思います。
送信側で処理できるなら1行当たりの文字数を制限された方がいいかと思うのですが。
又は、受信側で改行〜改行までの文字数をカウントしてある一定以上になったら改行コードを
付加するとか。


hhttp://msdn.microsoft.com/library/default.asp?url=/library/en-
us/shellcc/platform/commctls/richedit/richeditcontrols/richeditcontrolreference/richeditmessa
ges/em_settextex.asp
上記当たりで EM_ から始まる定数を名前からある程度判断して調べて見て下さい。

又、もっと高速に表示するなら置き換える方向で検討してください。
下記に追加書き込みと置き換え処理等の高速化比較のレスがありますので参考にして下さい。
hhttp://www.bcap.co.jp/hanafusa/logbbs/wforum.cgi?mode=allread&no=9220

投稿時間:2005/03/25(Fri) 21:48
投稿者名:kuro3
Eメール:
URL :
タイトル:
Re^3: 現在の条件では最速かも?
花ちゃんへ

どうもありがとうございました。
APIの仕様はこれから勉強してみます。

> 又は、受信側で改行〜改行までの文字数をカウントしてある一定以上になったら改行コードを
> 付加するとか。
上記を採用させていただきました。
かさねてお礼申し上げます。

> 下記に追加書き込みと置き換え処理等の高速化比較のレスがありますので参考にして下さい。
高速化には、多くのノウハウがあるのですね。

投稿時間:2005/03/25(Fri) 21:51
投稿者名:kuro3
Eメール:
URL :
タイトル:
「解決」 リッチテキストボックスを用いたターミナル パートU
みなさま、ご支援ありがとうございました。
おかげさまで無事完成の目処が立ちました。