my question is as is:How to detect if a scrollbar is at or not at the end of a richtextbox?
edit: when I say at the end I mean completely scrolled to the bottom, no
I used this code to get the current and maximum positions correctly:
const int SB_HORZ = 0x0000;
const int SB_VERT = 0x0001;
const int WM_HSCROLL = 0x0114;
const int WM_VSCROLL = 0x0115;
const int SB_THUMBPOSITION = 4;
private enum ScrollInfoMask : uint
{
SIF_RANGE = 0x1,
SIF_PAGE = 0x2,
SIF_POS = 0x4,
SIF_DISABLENOSCROLL = 0x8,
SIF_TRACKPOS = 0x10,
SIF_ALL = (SIF_RANGE | SIF_PAGE | SIF_POS | SIF_TRACKPOS)
}
[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO
{
public uint cbSize;
public uint fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
public int HScrollPosition
{
get
{
return GetScrollPos(Handle, SB_HORZ);
}
set
{
SetScrollPos((IntPtr)Handle, SB_HORZ, value, true);
PostMessageA((IntPtr)Handle, WM_HSCROLL, SB_THUMBPOSITION + 0x10000 * value, 0);
}
}
public int VScrollPosition
{
get
{
return GetScrollPos(Handle, SB_VERT);
}
set
{
SetScrollPos((IntPtr)Handle, SB_VERT, value, true);
PostMessageA((IntPtr)Handle, WM_VSCROLL, SB_THUMBPOSITION + 0x10000 * value, 0);
}
}
public int HScrollPositionMax
{
get
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.fMask = (uint)ScrollInfoMask.SIF_ALL;
scrollInfo.cbSize = (uint)Marshal.SizeOf(scrollInfo);
GetScrollInfo(Handle, SB_HORZ, ref scrollInfo);
return scrollInfo.nMax - (int)scrollInfo.nPage;
}
}
public int VScrollPositionMax
{
get
{
SCROLLINFO scrollInfo = new SCROLLINFO();
scrollInfo.fMask = (uint)ScrollInfoMask.SIF_ALL;
scrollInfo.cbSize = (uint)Marshal.SizeOf(scrollInfo);
GetScrollInfo(Handle, SB_VERT, ref scrollInfo);
return scrollInfo.nMax - (int)scrollInfo.nPage;
}
}
It's tedious to get the "correct" maximum value. You have to substract the nPage (large change) value of the max value GetScrollRange returns, and then you can compare it with the HScrollPosition property correctly, like:
if (_rtb.VScrollPosition == _rtb.VScrollPositionMax)
{
Debug.WriteLine("Scroll is at the bottom most edge");
}
One method is to use the GetScrollPos function. Here's kind of a long winded example of it using VB.NET.
http://www.codeproject.com/KB/vb/VbNetScrolling.aspx?print=true
if (richTextBox1.Size.Width - richTextBox1.ClientSize.Width > 10)
Sorry, you'll have to convert that to VB.NET yourself. Shouldn't be too hard :)
Check out the GetScrollRange and GetScrollPos API...
Private Const SBS_HORZ = 0
Private Const SBS_VERT = 1
<DllImport("user32.dll")> _
Public Function GetScrollRange(ByVal hWnd As IntPtr, ByVal nBar As Integer, _
ByRef lpMinPos As Integer, _
ByRef lpMaxPos As Integer) As Boolean
End Function
<DllImport("user32.dll")> _
Public Function GetScrollPos(ByVal hWnd As Integer, _
ByVal nBar As Integer) As Integer
End Function
// ...
Dim scrollMin as Integer = 0
Dim scrollMax as Integer = 0
If(GetScrollRange(rtb.Handle, SBS_VERT, scrollMin, scrollMax) Then
Dim pos as Integer = GetScrollPos(rtb.Handle, SBS_VERT)
// Detect if they're at the bottom
EndIf
Notes:
To determine if the scrollbar is visible, call GetWindowLong and check for WS_VSCROLL
To determine the max value the slider can get to, call GetScrollInfo; I think the maximum value is
scrollMax - largeChange + 1