检查RichTextBox ScrollBar thumb是否位于滚动条的底部

时间:2011-10-21 00:26:08

标签: c# winforms scrollbar richtextbox chat

我找到了这个链接WPF_Example,但它是用WPF编写的。我不是在WPF中编程,我在Windows Forms中这样做,并且没有理由想要将WPF RichTextBox嵌入到我的应用程序中以获得我需要的答案。

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

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

我需要复制它。我确实在SO: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;
}       

2 个答案:

答案 0 :(得分:2)

所以,这个问题的答案并不是非常复杂,但它相当冗长。关键是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;
}        

要测试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);

通话结束后,一个简单的公式可以确定滚动条拇指是否位于底部。基本上, info.rcScrollBar.Bottom info.rcScrollBar.Top 是屏幕上的位置,它们之间的区别将告诉您滚动条的大小,无论它在哪里在屏幕上。同时, info.xyThumbBottom 标记拇指按钮底部的位置。 “20”基本上是关于滚动条向下箭头的大小的猜测。你看,拇指按钮的底部实际上永远不会一直到滚动条的底部(这就是差异所给你的)所以你必须为向下按钮取下额外的金额。由于按钮的大小会根据用户的配置而有所不同,因此这有点不稳定,但这应该足以让您入门。

答案 1 :(得分:1)

我的朋友(专业程序员)给了我这个解决方案,它可以很好地工作(比几年前提供的解决方案更好):

var isAtBottom = rt.GetPositionFromCharIndex(rt.Text.Length).Y