Click here to Skip to main content
15,394,786 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
It looks like SendMessage user32 API cannot exceed beyond integer value.

I'm making a text editor application using vb2010 WinForm. Instead of scrolling with scrollbar, users can scroll directly on the richtextbox with the mouse, similar to adobe acrobat reader. To scroll richtextbox programatically I'm using SendMessage user32 API.

I have two problems:

1. If the text in richtextbox is big and I scrolled near the end of integer value then scrollbar will scroll back to its initial position.
2. The scrollbar value that has been set using SendMessage is not the same when we read it later with GetScrollPos. As a result, when I dragged the text using mouse, the richtextbox does not scroll smoothly at the beginning, it's jump.

What I have tried:

Public Class Form1
    Dim StartMouseDownPos As New Point
    Dim StartScrollBarPos As New Point
    Const WM_USER = &H400

    Public Declare Auto Function RtfScroll Lib "user32.dll" Alias "SendMessage" ( _
            ByVal hWnd As IntPtr, _
            ByVal Msg As Integer, _
            ByVal wParam As IntPtr, _
            ByRef lParam As System.Drawing.Point) As Integer

    Private Sub RichTextBox1_MouseDown(ByVal sender As System.Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles RichTextBox1.MouseDown
        'Capture the initial mouse position
        StartMouseDownPos.X = e.X
        StartMouseDownPos.Y = e.Y
        'Capture the initial scrollbar position
        RtfScroll(RichTextBox1.Handle, EM_GETSCROLLPOS, 0, StartScrollBarPos)
    End Sub

    Private Sub RichTextBox1_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles RichTextBox1.MouseMove
        'Verify left button is pressed while the mouse is moving
        If e.Button = Windows.Forms.MouseButtons.Left Then
            'Prevent the text in RichTextBox1 to be unintentionally selected when user dragged the text while the cursor shape at that moment is a hand.
            ActiveControl = Nothing
            NewScrollBarPos.X = StartScrollBarPos.X + (StartMouseDownPos.X - e.X)
            NewScrollBarPos.Y = StartScrollBarPos.Y + (StartMouseDownPos.Y - e.Y)
            RtfScroll(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, NewScrollBarPos)
        End If
    End Sub

I tried to change the problematic statement above: RtfScroll(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, NewScrollBarPos) with the following:

Public Declare Function GetScrollPos Lib "user32.dll" ( _
       ByVal hWnd As IntPtr, _
       ByVal nBar As Integer) As Integer

Public Declare Function SetScrollPos Lib "user32.dll" ( _
       ByVal hWnd As IntPtr, _
       ByVal nBar As Integer, _
       ByVal nPos As Integer, _
       ByVal bRedraw As Boolean) As Integer

Public Declare Function PostMessageA Lib "user32.dll" ( _
       ByVal hwnd As IntPtr, _
       ByVal wMsg As Integer, _
       ByVal wParam As Integer, _
       ByVal lParam As Integer) As Boolean

'Scroll the horizontal scrollbar according to the drag of the mouse
SetScrollPos(RichTextBox1.Handle, SBS_HORZ, NewScrollBarPos.X, True)
SetScrollPos(RichTextBox1.Handle, SBS_VERT, NewScrollBarPos.Y, True)
'Scroll the text according to the drag of the mouse
PostMessageA(RichTextBox1.Handle, WM_HSCROLL, SB_THUMBPOSITION + &H10000 * GetScrollPos(RichTextBox1.Handle, SBS_HORZ), Nothing)
PostMessageA(RichTextBox1.Handle, WM_VSCROLL, SB_THUMBPOSITION + &H10000 * GetScrollPos(RichTextBox1.Handle, SBS_VERT), Nothing)

The result is even worse: an overflow exception raised at multiplication of &H10000 * GetScrollPos(RichTextBox1.Handle, SBS_HORZ), Nothing), that happen when I tried to scroll beyond integer value.

So, my question is how to solve these two problems?
Updated 24-May-22 18:37pm

The POINT structore comprises two LONG values, not a single integer. See POINT structure (Windows) | Microsoft Docs[^]. So you should recreate that structure in your code and pass its address in the LPARAM variable.
Gunawan Harijadi 24-May-22 11:37am
Can we change / recreate the existing structure (Point) in VB? if that's the case, how?
All I know is to create a new structure, for example:
Public Structure systemInfo
Public cPU As String
Public memory As Long
End Structure
Dim mySystem, yourSystem As systemInfo
Richard MacCutchan 24-May-22 11:51am
Yes, as I stated in my answer above.
The arithmatic calculation of
&H10000 * GetScrollPos(RichTextBox1.Handle, SBS_VERT)
is not correct, it will cause OverflowException to rise. The correct calculation is
GetScrollPos(RichTextBox1.Handle, SBS_VERT) << 16 Or SB_THUMBPOSITION

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900