简体   繁体   English

使用 SendMessage user32 API 以编程方式滚动 RichTextBox 不能超过整数值

[英]Scroll RichTextBox programatically using SendMessage user32 API cannot exceed Integer value

I'm making a text editor application using vb2010 WinForm.我正在使用 vb2010 WinForm 制作一个文本编辑器应用程序。 Instead of scrolling with scrollbar, users can scroll directly on the richtextbox with the mouse, similar to adobe acrobat reader.不用滚动条滚动,用户可以直接用鼠标在richtextbox上滚动,类似于adobe acrobat reader。 To scroll richtextbox programatically I'm using SendMessage user32 API.要以编程方式滚动richtextbox,我正在使用 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.如果richtextbox 中的文本很大并且我在整数值的末尾附近滚动,那么滚动条将滚动回其初始位置。
  2. The scrollbar value that has been set using SendMessage is not the same when we read it later with GetScrollPos.使用 SendMessage 设置的滚动条值与我们稍后使用 GetScrollPos 读取时不一样。 As a result, when I dragged the text using mouse, the richtextbox does not scroll smoothly at the beginning, it's jump.结果,当我使用鼠标拖动文本时,richtextbox 开始时滚动不流畅,它是跳跃的。

Here's what I've done:这是我所做的:

Public Class Form1
    Dim StartMouseDownPos As New Point
    Dim StartScrollBarPos As New Point
    Const WM_USER = &H400
    Const EM_GETSCROLLPOS = WM_USER + 221
    Const EM_SETSCROLLPOS = WM_USER + 222

    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:我试图改变上面有问题的陈述: RtfScroll(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, NewScrollBarPos) 如下:

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.结果更糟:当我试图滚动超出整数值时,会在 &H10000 * GetScrollPos(RichTextBox1.Handle, SBS_HORZ), Nothing) 相乘时引发溢出异常。

So, my question is how to solve these two problems?那么,我的问题是如何解决这两个问题?

I've made a small program to find out what the cause of my problem, and it turns out that the problem is this: RtfScroll function alias "SendMessage" which uses Point as input doesn't get or set the correct value.我做了一个小程序来找出问题的原因,结果发现问题是这样的:使用 Point 作为输入的RtfScroll函数别名“SendMessage”没有获取或设置正确的值。 This doesn't happen to GetScrollPos , SetScrollPos , and PostMessageA .这不会发生在GetScrollPosSetScrollPosPostMessageA上。

So, don't use a combination of RtfScroll(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, New Point(countX, countY)) & RtfScroll(RichTextBox1.Handle, EM_GETSCROLLPOS, 0, point) .所以,不要使用RtfScroll(RichTextBox1.Handle, EM_SETSCROLLPOS, 0, New Point(countX, countY)) & RtfScroll(RichTextBox1.Handle, EM_GETSCROLLPOS, 0, point)的组合。

Just use a combination of GetScrollPos , SetScrollPos , and PostMessageA .只需使用GetScrollPosSetScrollPosPostMessageA的组合。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM