Home > Blockchain >  How do I know when the user can scroll a RichTextBox with forced ScrollBars
How do I know when the user can scroll a RichTextBox with forced ScrollBars

Time:10-11

I need the ScrollBars to be set to ForcedBoth but I also want to know when the ScrollBars' handles are visible and the user can scroll.

A boolean for both scrollbars would do

Here the user cannot scroll:
Here the user cant scroll

Here they can:
And here they can

I tried GetScrollInfo from Win32 API but it results in inconsistent results when zooming into the RichTextBox or removing a bunch of lines at once.

CodePudding user response:

If this is actually what you need to know about the state of the ScrollBars of your RichTextBox, use GetScrollBarInfo() to get this information, then test the values stored in the rgstate component of the returned SCROLLBARINFO struct.

When a ScrollBar is disabled, rgstate[0] is set to STATE_SYSTEM_UNAVAILABLE; the value at index 2 (page element), should be set to STATE_SYSTEM_INVISIBLE in this case.
When a ScrollBar is not present, the same value is STATE_SYSTEM_INVISIBLE
Otherwise, it's 0 (here, set to SBIdObj.STATE_SYSTEM_AVAILABLE = 0x00000000)

A sample method that can be used to test the ScrollBars. Call it as, e.g.,

var result = GetScrollBarsState(myRichTextBox.Handle);  

It returns a named tuple with the state of both ScrollBars set to the current SBIdObj value

public (SBRgState Vertical, SBRgState Horizontal) GetScrollBarsState(IntPtr controlHandle)
{
    var sbi = new SCROLLBARINFO() { cbSize = Marshal.SizeOf<SCROLLBARINFO>() };

    bool result = GetScrollBarInfo(controlHandle, SBIdObj.OBJID_VSCROLL, ref sbi);
    if (!result) throw new Exception("Failed to retrieve vertical ScrollBar info");
    var vert = (SBRgState)sbi.rgstate[0];

    result = GetScrollBarInfo(controlHandle, SBIdObj.OBJID_HSCROLL, ref sbi);
    if (!result) throw new Exception("Failed to retrieve horizontal ScrollBar info");

    return (vert, (SBRgState)sbi.rgstate[0]);
}

Declarations:

[DllImport("User32.dll", CharSet = CharSet.Auto, SetLastError = true)]
internal static extern bool GetScrollBarInfo(IntPtr hWnd, SBIdObj idObject, ref SCROLLBARINFO psbi);

[StructLayout(LayoutKind.Sequential)]
public struct SCROLLBARINFO {
    public int cbSize;
    public Rectangle rcScrollBar;
    public int dxyLineButton;
    public int xyThumbTop;
    public int xyThumbBottom;
    public int reserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public int[] rgstate;
}

// GetScrollBarInfo idObject
public enum SBIdObj : uint {
    OBJID_HSCROLL = 0xFFFFFFFA,
    OBJID_VSCROLL = 0xFFFFFFFB,
    OBJID_CLIENT = 0xFFFFFFFC
}

// SCROLLBARINFO rgstate flags
[Flags]
public enum SBRgState {
    STATE_SYSTEM_AVAILABLE = 0x00000000,
    STATE_SYSTEM_UNAVAILABLE = 0x00000001,
    STATE_SYSTEM_PRESSED = 0x00000008,
    STATE_SYSTEM_INVISIBLE = 0x00008000,
    STATE_SYSTEM_OFFSCREEN = 0x00010000,
}
  • Related