如何确定富文本框滚动条何时到达底部



这是我用 c# 编写的第一个代码,也是我对 Stackoverflow 的第一个问题......如果我做错了一切,请提前道歉!:-/

我试图实现由LarsTech编写的公共类RTFScrolledToBottom,该类被发布为回答了这里的问题: 从富文本框控件获取当前滚动位置?

在公共 Form1(( 代码块中,此行生成 CS1061 错误:

rtfScrolledBottom1.ScrolledToBottom += rtfScrolledBottom1_ScrolledToBottom;

object不包含ScrolledToBottom的定义,并且找不到接受类型object的第一个参数ScrolledToBottom可访问的扩展方法(您是否缺少 using 指令或程序集引用?

提前感谢您的任何帮助,指出我搞砸了什么!!

干杯!

namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
private object rtfScrolledBottom1;
public Form1()
{
InitializeComponent();
int rtfScrolledBottom1_ScrolledToBottom = 0;
rtfScrolledBottom1.ScrolledToBottom += rtfScrolledBottom1_ScrolledToBottom;
}
private void richTextBox1_TextChanged(object sender, EventArgs e)
{
}
}

public class RTFScrolledBottom : RichTextBox
{
public event EventHandler ScrolledToBottom;
private const int WM_VSCROLL = 0x115;
private const int WM_MOUSEWHEEL = 0x20A;
private const int WM_USER = 0x400;
private const int SB_VERT = 1;
private const int EM_SETSCROLLPOS = WM_USER + 222;
private const int EM_GETSCROLLPOS = WM_USER + 221;
[DllImport("user32.dll")]
private static extern bool GetScrollRange(IntPtr hWnd, int nBar, out int lpMinPos, out int lpMaxPos);
[DllImport("user32.dll")]
private static extern IntPtr SendMessage(IntPtr hWnd, Int32 wMsg, Int32 wParam, ref Point lParam);
public bool IsAtMaxScroll()
{
int minScroll;
int maxScroll;
GetScrollRange(this.Handle, SB_VERT, out minScroll, out maxScroll);
Point rtfPoint = Point.Empty;
SendMessage(this.Handle, EM_GETSCROLLPOS, 0, ref rtfPoint);
return (rtfPoint.Y + this.ClientSize.Height >= maxScroll);
}
protected virtual void OnScrolledToBottom(EventArgs e)
{
if (ScrolledToBottom != null)
ScrolledToBottom(this, e);
}
protected override void OnKeyUp(KeyEventArgs e)
{
if (IsAtMaxScroll())
OnScrolledToBottom(EventArgs.Empty);
base.OnKeyUp(e);
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_VSCROLL || m.Msg == WM_MOUSEWHEEL)
{
if (IsAtMaxScroll())
OnScrolledToBottom(EventArgs.Empty);
}
base.WndProc(ref m);
}
}
}

您已将rtfScrolledBottom1定义为对象,并且对象没有任何事件。您需要将其定义为RTFScrolledBottom.还可以从工具箱中删除RTFScrolledBottom控件的实例,并像使用任何其他控件一样使用它。

替代解决方案

作为您在链接帖子中找到的解决方案的替代方案,这是另一种解决方案,它无需创建派生控件即可与RichTextBox一起使用,同时您可以将逻辑放在派生控件中并使其更可重用,就像在链接帖子中所做的那样。

您可以处理RichTextBox事件VScroll并通过调用GetScrollInfo方法来获取滚动位置。然后在SCROLLINFO如果nPage + nPos == nMax,则表示滚动位于底部:

[StructLayout(LayoutKind.Sequential)]
struct SCROLLINFO {
public int cbSize;
public ScrollInfoMask fMask;
public int nMin;
public int nMax;
public uint nPage;
public int nPos;
public int nTrackPos;
}
public 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),
}
[DllImport("user32.dll")]
private static extern bool GetScrollInfo(IntPtr hwnd, SBOrientation fnBar, 
ref SCROLLINFO lpsi);
public enum SBOrientation : int { SB_HORZ = 0x0, SB_VERT = 0x1 }
private void richTextBox1_VScroll(object sender, EventArgs e)
{
var info = new SCROLLINFO() { 
cbSize = (Marshal.SizeOf<SCROLLINFO>()),
fMask = ScrollInfoMask.SIF_ALL 
};
GetScrollInfo(richTextBox1.Handle, SBOrientation.SB_VERT, ref info);
if (info.nPage + info.nPos == info.nMax)
{
//VScroll is at bottom
}
}

最新更新