Results 1 to 5 of 5

Thread: [2008] Synchronized RichTextBox scrolling

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    [2008] Synchronized RichTextBox scrolling

    Hi!

    Here is my own, relatively easy way to make the scrolling between two RichTextBoxes synchronized.

    Note that there is a fundamental difference between this way and all the other ways I have found on the internet:
    In my version, the textboxes are NOT always in the exact same scrollposition.

    Instead, if you scroll one textbox by x amount, the other textbox will also scroll by x amount.

    What's the difference, you may ask..? Well, suppose you have two identical files open in the two RTBs. If you synchronize their scrolling by setting their scrollpositions equal, you will always see the same piece of text in both RTBs. Pretty useless if you ask me, no?

    With my version, you can first disable synchronized scrolling. Then you scroll one RTB, let's say to about halfway down (while not touching the other).
    Then you enable synchronized scrolling and scroll the first RTB by some amount. The other RTB will scroll by the same amount, but NOT jump to the same scrollposition.

    This way you can view two pieces of text within the same file simultaneously, while also scrolling them simultaneously.

    If you still don't understand, check out the next post for a few images to explain things better.

    Anyway enough blabbering, here is how I did it.
    -------------------------------------------------------


    Create a blank form (Form1) and simply add these controls (preferably with the listed properties):
    - A Checkbox called "chk".
    - A RichTextBox called "RTB1".
    - A RichTextBox called "RTB2".

    I'm not sure if this is necessary but in my form I set the WordWrap of both RTBs to False, and the ScrollBar to ForcedVertical.


    Then, simply add the following code:
    vb.net Code:
    1. Public Class Form1
    2.  
    3.     ' Constants and SendMessage function
    4.     Const WM_USER As Integer = &H400
    5.     Const EM_GETSCROLLPOS As Integer = WM_USER + 221
    6.     Const EM_SETSCROLLPOS As Integer = WM_USER + 222
    7.     Declare Function SendMessage Lib "user32.dll" Alias "SendMessageW" (ByVal hWnd As IntPtr, ByVal msg As Integer, ByVal wParam As Integer, ByRef lParam As Point) As Integer
    8.  
    9.     ' Scrollpositions of rtb1 and rtb2
    10.     Dim ptScrollPos_RTB1, ptScrollPos_RTB2 As Point
    11.  
    12.     ' Wether the scroll was made by the user (false) or by the synched scrolling function (true)
    13.     Dim blnScrolled_RTB1, blnScrolled_RTB2 As Boolean
    14.  
    15.     Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
    16.  
    17.         ' Load the RTB's with textfile
    18.         Dim strFilePath As String = ""
    19.         Using ofd As New OpenFileDialog With {.Filter = "Text files (*.txt)|*.txt|All files|*.*", .Title = "Open text file"}
    20.             If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then
    21.                 strFilePath = ofd.FileName
    22.  
    23.                 RTB1.LoadFile(strFilePath, RichTextBoxStreamType.PlainText)
    24.                 RTB2.LoadFile(strFilePath, RichTextBoxStreamType.PlainText)
    25.             Else
    26.                 MessageBox.Show("You are encouraged to load a large file.", "Choose file", MessageBoxButtons.OK, MessageBoxIcon.Warning)
    27.             End If
    28.         End Using
    29.  
    30.         ' Set the default scrollposition of RTB's
    31.         SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, ptScrollPos_RTB1)
    32.         SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, ptScrollPos_RTB2)
    33.     End Sub
    34.  
    35.     Private Sub RTB1_VScroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RTB1.VScroll
    36.         ' Do not continue if the scroll was made by this program and not by the user (to prevent endless loops)
    37.         If blnScrolled_RTB2 Then Exit Sub
    38.  
    39.         ' Set a flag so RTB2 knows it is scrolled by RTB1 and not by the user
    40.         blnScrolled_RTB1 = True
    41.  
    42.         Dim diff As Integer
    43.  
    44.         ' Check scrollposition after scrolling
    45.         Dim pt As Point
    46.         SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, pt)
    47.  
    48.         ' Compare Y-value (height) with scrollposition before scrolling
    49.         diff = pt.Y - ptScrollPos_RTB1.Y
    50.  
    51.         ' Set RTB1 scrollposition variable to new scrollposition
    52.         ptScrollPos_RTB1 = pt
    53.  
    54.         ' Only sync scrolling when checkbox is checked
    55.         If chk.Checked Then
    56.             ' Get RTB2 scrollposition
    57.             Dim pt2 As Point
    58.             SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, pt2)
    59.  
    60.             ' Set RTB2 scrollpos Y (height) to old scrollposition + the difference in RTB1 scrollposition
    61.             SendMessage(RTB2.Handle, EM_SETSCROLLPOS, 0, New Point(pt.X, diff + pt2.Y))
    62.         End If
    63.  
    64.         ' Re-Set the flag
    65.         blnScrolled_RTB1 = False
    66.     End Sub
    67.  
    68.     Private Sub RTB2_VScroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RTB2.VScroll
    69.         ' Do not continue if the scroll was made by this program and not by the user (to prevent endless loops)
    70.         If blnScrolled_RTB1 Then Exit Sub
    71.  
    72.         ' Set a flag so RTB1 knows it is scrolled by RTB2 and not by the user
    73.         blnScrolled_RTB2 = True
    74.  
    75.         Dim diff As Integer
    76.  
    77.         ' Check scrollposition after scrolling
    78.         Dim pt As Point
    79.         SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, pt)
    80.  
    81.         ' Compare Y-value (height) with scrollposition before scrolling
    82.         diff = pt.Y - ptScrollPos_RTB2.Y
    83.  
    84.         ' Set RTB2 scrollposition variable to new scrollposition
    85.         ptScrollPos_RTB2 = pt
    86.  
    87.         ' Only sync scrolling if checkbox is checked
    88.         If chk.Checked Then
    89.             ' Get RTB1 scrollposition
    90.             Dim pt2 As Point
    91.             SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, pt2)
    92.  
    93.             ' Set RTB2 scrollpos Y (height) to old scrollposition + the difference in RTB2 scrollposition
    94.             SendMessage(RTB1.Handle, EM_SETSCROLLPOS, 0, New Point(pt.X, diff + pt2.Y))
    95.         End If
    96.  
    97.         ' Re-Set the flag
    98.         blnScrolled_RTB2 = False
    99.     End Sub
    100. End Class


    How this works:

    1. After loading the chosen textfile to both RTBs, I store their scrollpositions in the variables ptScrollPos_RTB1 and ptScrollPos_RTB2.

    2. In the VScroll (vertical scroll) event of both textboxes, I get the new scrollposition (after scrolling) and compare that to the old scrollposition (the variables above). I create an integer diff and set it to the difference between the old and the new scrollpositions Y-value.
    This difference is exactly the amount the other RTB needs to scroll.

    3. I 'reset' the ptScrollPos_RTB variables to the new scrollposition.

    4. If the checkbox is checked, I read the scrollposition of the other RTB. Then I set its scrollposition to the new point, namely the old point + the diff Y-value.

    5. To stop an endless loop from happening (user scrolls RTB1 which fires RTB2 scroll, which fires RTB1 scroll, which fires RTB2 scroll etc etc etc) I introduce a boolean variable blnScrolled_RTB(1/2).
    At the start of the VScroll event I set this variable to True, and at the end I set it to False.
    If this variable is True at the start of the VScroll event (of the other RTB), it means this VScroll event is fired by the other RTB scrolling and thus should NOT be handled.



    I hope I explained it enough and I hope you can use it, feel free to do so...
    Last edited by NickThissen; Aug 26th, 2008 at 12:53 PM.

  2. #2

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [2008] Synchronized RichTextBox scrolling

    As promised, some screenshots to explain what this does exactly:


    Here we see two RTBs each containing the same text (not required obviously, but easy for this example). RTB 1 is clearly scrolled down a bit while RTB2 is at the top:


    Now, let's see what happens with the 'usual' way of synched scrolling (note, this is NOT what my example does!):


    You can see that, after scrolling, the second RTB has jumped to the same scrollposition as the first RTB (note the exact same text). It does not keep the same distance.


    Now, my example does not do this. My example remembers the distance between the two scrollpositions and after scrolling, it looks like this:


    Note now that the RTBs are not in the same position, but they still scroll simultaneously (not very easy to show that by a screenshot hehe...)

  3. #3
    Addicted Member
    Join Date
    Jun 2008
    Location
    Macedonia
    Posts
    188

    Re: [2008] Synchronized RichTextBox scrolling

    Is possible to Synchronized a listbox and how if you know
    MACEDONIA 4EVER

  4. #4

  5. #5
    Addicted Member
    Join Date
    Jun 2008
    Location
    Macedonia
    Posts
    188

    Re: [2008] Synchronized RichTextBox scrolling

    Yes i mak taht but problem is that listbox dont have this event VScroll ok nvm
    MACEDONIA 4EVER

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width