• 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