web-dev-qa-db-ja.com

バックグラウンドワーカーによって更新されているマルチラインテキストボックスの下部まで自動スクロール

タスクを実行するように設定されたバックグラウンドワーカーコントロールがあり、デリゲートプロシージャを使用してメインUIのマルチラインテキストボックスを更新します。これはすべて完全に機能していますが、更新がテキストボックスの下部からスクロールすると、スクロールバーが表示されますが、継続的に更新すると、テキストボックスが上部にロックされたままになります。理想的には、テキストボックスを一番下まで自動スクロールして、最新のエントリをリアルタイムで表示したいです。これを実装する最良の方法は何でしょうか?

scrolltocaret()メソッドを使用しようとしましたが、その前に_SelectionStart = txtlog.Text.Length_コマンドがある場合とない場合があります。多分私はそれを間違った場所に置いていますか?

以下のコードサンプル:

委任コード:

_Delegate Sub updateresults_delegate(ByVal textbox As TextBox, ByVal text As String)

Private Sub updatelog_threadsafe(ByVal textbox As TextBox, ByVal text As String)
            If textbox.InvokeRequired Then
                Dim mydelegate As New updateresults_delegate(AddressOf updatelog_threadsafe)
                Me.Invoke(mydelegate, New Object() {textbox, text})
                'Me.txtlog.SelectionStart = txtlog.Text.Length
                'Me.txtlog.ScrollToCaret()
            Else
                textbox.Text = text
            End If
        End Sub
_

主なバックグラウンドワーカーのアクティビティ:

_For i As Integer = val1 To val2
'generate an IP address from split Host parts and current value of i
                Host = s1(0) & "." & s1(1) & "." & s1(2) & "." & i
                Try 'attempt to ping the IP
                    Dim reply As PingReply = pingsender.Send(Host, timeoutval, buffer, options)
                    If reply.Status = IPStatus.Success Then
                        name = System.Net.Dns.GetHostEntry(Host)'get DNS entry
                        resulttext += String.Format("{1} - {2}: reply: Bytes={3} time{4} TTL={5}{0}", vbCrLf, name.HostName, reply.Address.ToString, reply.Buffer.Length, getms(reply.RoundtripTime), reply.Options.Ttl) 'print out success text
                    Else
                        resulttext += String.Format("      {1}: Ping failed. {2}{0}", vbCrLf, Host, reply.Status.ToString) 'print out fail text
                    End If
                    updatelog_threadsafe(txtlog, resulttext) 'send text to textbox

            System.Threading.Thread.Sleep(1000)
        Catch ex As Exception

        End Try
    Next
_

私の主な質問は次のとおりだと思います:textbox.scrolltocaret()は、私が欲しいものに使用する正しい方法であることはかなり確かですが、それを置くのに最適な場所はどこですか?私はデリゲート、メインバックグラウンドワーカー、およびrunworkerasync()メソッドの前後でそれを試しました。これらのどれもうまくいきませんでした、そして今私は困惑しています!

16
almg

このようにしてみてください:

'textbox.Text = text
textbox.AppendText(text)

コメントアウトしたコードはGUIスレッドで実行されていなかったため、M Granjaが指摘したように、AppendTextは自動的にボックス内の追加テキストまでスクロールするため、ScrollToCaretを呼び出す必要はありません。

26
LarsTech

xxx.SetFocus 'xxx =テキストボックスの名前

SendKeys "^ {END}" '最終行にポップ

0
peter