检查 RichTextBox ScrollBar 拇指是否位于滚动条底部

3 c# chat scrollbar richtextbox winforms

我找到了这个链接WPF_Example,但它是用 WPF 编写的。我不是在 WPF 中编程,而是在 Windows 窗体中执行此操作,并且没有真正的理由想要将 WPF RichTextBox 嵌入到我的应用程序中只是为了获得我需要的答案。

有没有办法使用 WindowsForms(不是 WPF)来确定 RichTextBox 滚动条滑块是否位于滚动条的底部?

这样做的目的是允许正在 RTF 框中查看聊天的用户向上滚动,并且在添加文本时,如果向上滚动,则不要向下滚动。想想 mIRC 如何处理聊天;如果您位于聊天框的底部,文本将自动滚动到视图中;如果您向上移动哪怕一行,文本就会添加而无需滚动。

我需要复制这一点。我确实在这里找到了这个链接: List_ViewScroll,但我不确定它是否适用于这种情况。

任何帮助将不胜感激:)

解决

使用这个课程,我能够让它发挥作用。非常感谢下面的人指出并澄清了其中的一些内容:

internal class Scrollinfo
{
    public const uint ObjidVscroll = 0xFFFFFFFB;

    [DllImport("user32.dll", SetLastError = true, EntryPoint = "GetScrollBarInfo")]
    private static extern int GetScrollBarInfo(IntPtr hWnd,
                                               uint idObject,
                                               ref Scrollbarinfo psbi);

    internal static bool CheckBottom(RichTextBox rtb)
    {


        var info = new Scrollbarinfo();
        info.CbSize = Marshal.SizeOf(info);

        var res = GetScrollBarInfo(rtb.Handle,
                                   ObjidVscroll,
                                   ref info);

        var isAtBottom = info.XyThumbBottom > (info.RcScrollBar.Bottom - info.RcScrollBar.Top - (info.DxyLineButton*2));
        return isAtBottom;
    }
}

public struct Scrollbarinfo
{
    public int CbSize; 
    public Rect RcScrollBar;
    public int DxyLineButton;
    public int XyThumbTop;
    public int XyThumbBottom;
    public int Reserved;
    [MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
    public int[] Rgstate;
}

public struct Rect
{
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}       
Run Code Online (Sandbox Code Playgroud)

Aro*_*tte 5

所以,这个问题的答案并不是非常复杂,但相当冗长。关键是 Win32 API 函数 GetScrollBarInfo,从 C# 调用它相当容易。您需要在表单中使用以下定义才能进行调用...

[DllImport("user32.dll", SetLastError = true, EntryPoint = "GetScrollBarInfo")]
private static extern int GetScrollBarInfo(IntPtr hWnd,
    uint idObject, ref SCROLLBARINFO psbi);

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

public struct RECT {
    public int Left;
    public int Top;
    public int Right;
    public int Bottom;
}        
Run Code Online (Sandbox Code Playgroud)

要测试 GetScrollBarInfo,请考虑创建一个带有 RichTextBox 和按钮的表单。在按钮的单击事件中,进行以下调用(假设您的 RichTextBox 名为“richTextBox1”)...

uint OBJID_VSCROLL = 0xFFFFFFFB;

SCROLLBARINFO info = new SCROLLBARINFO();
info.cbSize = Marshal.SizeOf(info);

int res = GetScrollBarInfo(richTextBox1.Handle, OBJID_VSCROLL, ref info);
bool isAtBottom = info.xyThumbBottom >
    (info.rcScrollBar.Bottom - info.rcScrollBar.Top - 20);
Run Code Online (Sandbox Code Playgroud)

调用后,一个简单的公式就可以判断滚动条滑块是否在底部。本质上,info.rcScrollBar.Bottominfo.rcScrollBar.Top是屏幕上的位置,它们之间的差异将告诉您滚动条的大小,无论它位于屏幕上的哪个位置。同时,info.xyThumbBottom标记了拇指按钮底部的位置。“20”基本上是对滚动条向下箭头的大小的猜测。您会看到,拇指按钮的底部实际上永远不会一直到达滚动条的底部(这就是差异所给您的),因此您必须为向下按钮减少额外的量。无可否认,这有点不稳定,因为按钮的大小会根据用户的配置而有所不同,但这应该足以让您开始。