检查 RichTextBox ScrollBar 拇指是否位于滚动条底部
有没有办法使用 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;
}
I found this link WPF_Example, but it is written in WPF. I am not programming in WPF, I am doing this in Windows Forms, and have no real reason to want to embed a WPF RichTextBox into my app just to obtain the answer I need.
Is there not a way, using WindowsForms (NOT WPF), to figure out if the RichTextBox scroll-bar thumb is at the bottom of the scroll bar?
The purpose of this is to allow our users, who are viewing the chat in the RTF box, to scroll up, and when text is added, NOT SCROLL DOWN, if they are scrolled up. Think of how mIRC handles chat; if you are at the bottom of the chat box, text will auto scroll into view; if you move up even one line, text is added w/o having to scroll.
I need to replicate that. I did find this link here on SO: List_ViewScroll, but i am not sure if it applies in this case.
Any help would be greatly appriciated :)
RESOLUTION
Using this class, I was able to get it to work. Thank you very much to the person below who pointed it out, and clarified some bits of it:
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;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
所以,这个问题的答案并不是非常复杂,但相当冗长。关键是 Win32 API 函数 GetScrollBarInfo,从 C# 调用它相当容易。您需要在表单中使用以下定义才能进行调用...
要测试 GetScrollBarInfo,请考虑创建一个包含 RichTextBox 和按钮的表单。在按钮的单击事件中,进行以下调用(假设您的 RichTextBox 名为“richTextBox1”)...
调用后,一个简单的公式可以确定滚动条滑块是否位于底部。本质上,info.rcScrollBar.Bottom 和 info.rcScrollBar.Top 是屏幕上的位置,它们之间的差异将告诉您滚动条的大小,无论滚动条位于何处出现在屏幕上。同时,info.xyThumbBottom标记了拇指按钮底部的位置。 “20”基本上是对滚动条向下箭头的大小的猜测。您会看到,拇指按钮的底部实际上永远不会一直到达滚动条的底部(这就是差异所给您的),因此您必须为向下按钮减少额外的量。无可否认,这有点不稳定,因为按钮的大小会根据用户的配置而有所不同,但这应该足以让您开始。
So, the answer to this question is not incredibly complicated, but it is fairly verbose. The key is the Win32 API function GetScrollBarInfo, which is fairly easy to call from C#. You'll need to the following definitions in your form to make the call...
To test out GetScrollBarInfo, consider creating a form with a RichTextBox and a button. In the click event for the button, make the following call (assuming your RichTextBox is named "richTextBox1")...
After the call, a simple formula can determine whether or not the scroll bar thumb is at the bottom. Essentially, info.rcScrollBar.Bottom and info.rcScrollBar.Top are positions on the screen and the difference between them will tell you the size of the scroll bar no matter where it is on the screen. Meanwhile, info.xyThumbBottom marks the position of the bottom of the thumb button. The "20" is basically guess as to the size of the scroll bar's down arrow. You see, the bottom of the thumb button will never actually be all the way to the bottom of the scroll bar, (which is what the difference gives you) so you have to take off an additional amount for the down button. This is admittedly somewhat volatile given that the button's size will be different depending on users' configuration, but this should be enough to get you started.
我的朋友(专家程序员)给了我这个解决方案,它工作得很好(比几年前提供的解决方案更好):
var isAtBottom = rt.GetPositionFromCharIndex(rt.Text.Length).Y < rt.高度;
My friend (expert programmer) gave me this solution, which works perfectly (better than the solution offered years ago):
var isAtBottom = rt.GetPositionFromCharIndex(rt.Text.Length).Y < rt.Height;