-
Aug 26th, 2008, 12:49 PM
#1
[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:
Public Class Form1 ' Constants and SendMessage function Const WM_USER As Integer = &H400 Const EM_GETSCROLLPOS As Integer = WM_USER + 221 Const EM_SETSCROLLPOS As Integer = WM_USER + 222 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 ' Scrollpositions of rtb1 and rtb2 Dim ptScrollPos_RTB1, ptScrollPos_RTB2 As Point ' Wether the scroll was made by the user (false) or by the synched scrolling function (true) Dim blnScrolled_RTB1, blnScrolled_RTB2 As Boolean Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load ' Load the RTB's with textfile Dim strFilePath As String = "" Using ofd As New OpenFileDialog With {.Filter = "Text files (*.txt)|*.txt|All files|*.*", .Title = "Open text file"} If ofd.ShowDialog = Windows.Forms.DialogResult.OK Then strFilePath = ofd.FileName RTB1.LoadFile(strFilePath, RichTextBoxStreamType.PlainText) RTB2.LoadFile(strFilePath, RichTextBoxStreamType.PlainText) Else MessageBox.Show("You are encouraged to load a large file.", "Choose file", MessageBoxButtons.OK, MessageBoxIcon.Warning) End If End Using ' Set the default scrollposition of RTB's SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, ptScrollPos_RTB1) SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, ptScrollPos_RTB2) End Sub Private Sub RTB1_VScroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RTB1.VScroll ' Do not continue if the scroll was made by this program and not by the user (to prevent endless loops) If blnScrolled_RTB2 Then Exit Sub ' Set a flag so RTB2 knows it is scrolled by RTB1 and not by the user blnScrolled_RTB1 = True Dim diff As Integer ' Check scrollposition after scrolling Dim pt As Point SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, pt) ' Compare Y-value (height) with scrollposition before scrolling diff = pt.Y - ptScrollPos_RTB1.Y ' Set RTB1 scrollposition variable to new scrollposition ptScrollPos_RTB1 = pt ' Only sync scrolling when checkbox is checked If chk.Checked Then ' Get RTB2 scrollposition Dim pt2 As Point SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, pt2) ' Set RTB2 scrollpos Y (height) to old scrollposition + the difference in RTB1 scrollposition SendMessage(RTB2.Handle, EM_SETSCROLLPOS, 0, New Point(pt.X, diff + pt2.Y)) End If ' Re-Set the flag blnScrolled_RTB1 = False End Sub Private Sub RTB2_VScroll(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RTB2.VScroll ' Do not continue if the scroll was made by this program and not by the user (to prevent endless loops) If blnScrolled_RTB1 Then Exit Sub ' Set a flag so RTB1 knows it is scrolled by RTB2 and not by the user blnScrolled_RTB2 = True Dim diff As Integer ' Check scrollposition after scrolling Dim pt As Point SendMessage(RTB2.Handle, EM_GETSCROLLPOS, 0, pt) ' Compare Y-value (height) with scrollposition before scrolling diff = pt.Y - ptScrollPos_RTB2.Y ' Set RTB2 scrollposition variable to new scrollposition ptScrollPos_RTB2 = pt ' Only sync scrolling if checkbox is checked If chk.Checked Then ' Get RTB1 scrollposition Dim pt2 As Point SendMessage(RTB1.Handle, EM_GETSCROLLPOS, 0, pt2) ' Set RTB2 scrollpos Y (height) to old scrollposition + the difference in RTB2 scrollposition SendMessage(RTB1.Handle, EM_SETSCROLLPOS, 0, New Point(pt.X, diff + pt2.Y)) End If ' Re-Set the flag blnScrolled_RTB2 = False End Sub 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.
-
Aug 26th, 2008, 12:57 PM
#2
-
Jan 23rd, 2010, 05:45 AM
#3
Addicted Member
Re: [2008] Synchronized RichTextBox scrolling
Is possible to Synchronized a listbox and how if you know
-
Jan 23rd, 2010, 05:50 AM
#4
Re: [2008] Synchronized RichTextBox scrolling
I've no idea. Try replacing RTB1 with ListBox1 and RTB2 with ListBox2 (except where I'm loading the text files), then you will see if it works. I doubt it though.
-
Jan 24th, 2010, 07:08 AM
#5
Addicted Member
Re: [2008] Synchronized RichTextBox scrolling
Yes i mak taht but problem is that listbox dont have this event VScroll ok nvm
Posting Permissions
- You may not post new threads
- You may not post replies
- You may not post attachments
- You may not edit your posts
-
Forum Rules
|
Click Here to Expand Forum to Full Width
|