• Solution : 使用 API : GetScrollInfo
TextBox 预设没有 Scroll 的触发事件,比较难开发
如果改成 RichTextBox,就有 VScroll (垂直卷动,水平卷动是 HScroll) 的触发事件,
再来用 API 去处理判断是否卷动到最后一行
以你的需求,底下的程式码要改成 加上一个 Boolean 值记录是否已经卷动到最后一行
卷动到最后一行的瞬间,即启动 下一步 的按钮,或是改变某个记录的变数值,
好让 点按钮后 知道使用者是否已卷动到最后一行
▼ 卷动前
▼ 卷动到最后一行,以下的事件都会触发
(1) 滑鼠拖曳 Scrollbar 到最后一行
(2) 文字选取使 Scrollbar 卷动到最后一行
(3) 点方向键 ↓ 使 Scrollbar 卷动到最后一行
• 方法 :
使用 API 函数 GetScrollInfo() 记录资料到 SCROLLINFO Structure 后
再用 si.nPos / (si.nMax - si.nPage) 得到 Scrollbar 的 ratio (0 代表第一行、1 代表最后一行)
ratio 大于 1 则代表卷动到最后一行
• 程式码 (VB 2010) :
将以下程式码贴到一个 Form 中
需要 1 个 RichTextBox 物件,命名为 "RichTextBox1"
复制程式
'[Info.] The following codes show how to detect an event that
' user scroll the scrollbars in a RichTextBox to the end
'
' *Required controls :
' 1x Form
' 1x RichTextBox named as "RichTextBox1"
Imports System.Runtime.InteropServices
Public Class Form1
'========== API ==========
<StructLayout(LayoutKind.Sequential)> Public Structure SCROLLINFO
Public cbSize As Integer
Public fMask As Integer
Public nMin As Integer
Public nMax As Integer
Public nPage As Integer
Public nPos As Integer
Public nTrackPos As Integer
End Structure
Public Declare Function GetScrollInfo Lib "user32" Alias "GetScrollInfo" ( _
ByVal hWnd As IntPtr, _
ByVal nBar As Integer, _
<MarshalAs(UnmanagedType.Struct)> ByRef lpScrollInfo As SCROLLINFO) As Integer
Private Const SB_HORZ As Integer = 0
Private Const SB_VERT As Integer = 1
Private Const SIF_RANGE As Integer = &H1
Private Const SIF_PAGE As Integer = &H2
Private Const SIF_POS As Integer = &H4
Private Const SIF_DISABLENOSCROLL As Integer = &H8
Private Const SIF_TRACKPOS As Integer = &H10
Private Const SIF_ALL As Integer = (SIF_RANGE Or SIF_PAGE Or SIF_POS Or SIF_TRACKPOS)
'========== Records ==========
Dim var_last_scrollbarRatio As Double 'Record last scrollbard ratio, used in 'check_scrollbar_ratio()' func.
'========== Functions ==========
'\brief Get user-defined scrollbar info
'\param ByVal hwnd As System.IntPtr | Handle of object
' ByVal iMode As Integer | Mode (Integer)
' ByRef si As SCROLLINFO | 'SCROLLINFO' structure
'\return Result of 'GetScrollInfo' API func.
Private Function get_scrollbarInfo(ByVal hwnd As System.IntPtr, ByVal iMode As Integer, _
ByRef si As SCROLLINFO) As Integer
Dim iRst As Integer 'Result
With si
.fMask = SIF_ALL
.cbSize = Len(si)
iRst = GetScrollInfo(hwnd, iMode, si)
End With
Return iRst
End Function
'\brief Get scrollbar value/max (Ratio)
'\param ByRef si As SCROLLINFO | 'SCROLLINFO' structure
'\return Double type : 0 ~ 1, 0 as first line, 1 as last line
Private Function get_scrollbarRatio(ByRef si As SCROLLINFO) As Double
If 0 <> (si.nMax - si.nPage) Then
Return si.nPos / (si.nMax - si.nPage)
Else
Return 0
End If
End Function
'\brief Check scrollbar ratio (User-defined)
'
Private Sub check_scrollbar_ratio()
Dim si As SCROLLINFO
Dim iRst As Integer
Dim dRatio As Double
iRst = get_scrollbarInfo(RichTextBox1.Handle, SB_VERT, si)
dRatio = get_scrollbarRatio(si)
'' Debug.Print("Scrollbar ratio : " & dRatio) '_DEBUG_
'Ratio must exceed 1 and it's not equal to last recorded ratio
' and last recorded ratio is lower than 1
' (Means that there are two states : one is not scrolled to the end, and otherwise)
If dRatio >= 1 And dRatio <> var_last_scrollbarRatio And var_last_scrollbarRatio < 1 Then
MessageBox.Show("You have scrolled to last line !!", "Scrollbar said", _
MessageBoxButtons.OK, MessageBoxIcon.Information)
End If
'Record last ratio
var_last_scrollbarRatio = dRatio
End Sub
'========== Object events ==========
Private Sub RichTextBox1_VScroll(ByVal sender As Object, ByVal e As System.EventArgs) Handles RichTextBox1.VScroll
check_scrollbar_ratio()
End Sub
End Class
by Ebola