Inconsistent Results with RichTextBox ScrollToCaret

后端 未结 4 775
-上瘾入骨i
-上瘾入骨i 2020-12-20 16:18

I am working with a RichTextBox in C#. It exists on a TabPage. When the TabPage is selected, I aim to populate the RichTextBox, and scroll to the end. I have tried the sligh

相关标签:
4条回答
  • 2020-12-20 16:42

    I have the same problem, I guess a RTB is almost quite managed by Windows Messages so it sounds a bit like a rabbit warren. I don t know, therefore, the reason for the alternating output (but it has slightly a bug taste). I am concerned with this RTB.Scrolltocaret flickering output but in a VB program. Compliments for your drastic solution: It works perfectly.

    Should anyone encounter this anomaly in that programming environment, here's the VB code

    Imports System.Runtime.InteropServices
    Public Class Form
    <DllImport("user32.dll",CharSet:=CharSet.Auto)> _
    Public Shared Function SendMessage( _
    ByVal hWnd As IntPtr, _
    ByVal wMsg As Integer, _
    ByVal wParam As IntPtr, _
    ByVal lParam As IntPtr) As Integer
    End Function
    Const WM_SCROLL = 277
    Const SB_PAGEBOTTOM = 7
    Sub ScrollToBottom(ByVal RTBName As RichTextBox)
       SendMessage(RTBName.Handle, _
                   WM_SCROLL, _
                   SB_PAGEBOTTOM, _
                   IntPtr.Zero)
    End Sub 'then call ScrollToBottom instead of ScrollToCaret
    
    0 讨论(0)
  • 2020-12-20 16:44

    I have encountered the same bug (now 7+ years old), of ScrollToCaret() jumping alternatively between the last line and almost the last line. Another solution which avoids using unmanaged code is to call ScrollToCaret() twice.

    RichBox.Select(TheLocationYouWantToScrollTo, 0);
    RichBox.ScrollToCaret();
    RichBox.ScrollToCaret();
    

    This approach can sometimes produce a little screen flicker (not bad, but not super smooth) because it is scrolling to one line and then the other. You might try to solve the slight flicker this way, but it won't work:

    RichBox.SuspendLayout(); // I won't actually suspend this layout
    RichBox.Select(TheLocationYouWantToScrollTo, 0);
    RichBox.ScrollToCaret();
    RichBox.ScrollToCaret();
    RichBox.ResumeLayout();
    

    You can also reduce flicker by making sure the new Location is on a new line:

    RichBox.Select(TheLocationYouWantToScrollTo, 0)
    if (RichBox.Transcription.GetFirstCharIndexOfCurrentLine() != ThePriorCharIndexOfCurrentLine)
    {
       RichBox.ScrollToCaret();
       RichBox.ScrollToCaret(); 
    }
    

    This reduces flicker by only scrolling when we are at a new line.

    0 讨论(0)
  • 2020-12-20 17:02

    I did some further experimentation with ScrollToCaret and it just does not end up in the same position every time. Since my goal is limited to only scrolling all the way to the bottom, it was then a good candidate for sending the WM_VSCROLL message (277, or 0x115) to the control, with wParam of SB_PAGEBOTTOM (7). This consistently scrolls all the way to the very bottom exactly like I needed:

    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    private static extern int SendMessage(IntPtr hWnd, int wMsg, IntPtr wParam, IntPtr lParam);
    private const int WM_VSCROLL = 277;
    private const int SB_PAGEBOTTOM = 7;
    
    public static void ScrollToBottom(RichTextBox MyRichTextBox)
    {
        SendMessage(MyRichTextBox.Handle, WM_VSCROLL, (IntPtr)SB_PAGEBOTTOM, IntPtr.Zero);
    }
    
    0 讨论(0)
  • 2020-12-20 17:05

    Change this to fit your working code..

    String gotoCaret = "Something on this line.";
    int position = textBox.Text.IndexOf(gotoCaret);
    MyRichTextBox.SelectionStart = position;
    MyRichTextBox.ScrollToCaret();
    
    0 讨论(0)
提交回复
热议问题