c# MouseWheel Scroll 和 RTB VScroll 事件
Posted
技术标签:
【中文标题】c# MouseWheel Scroll 和 RTB VScroll 事件【英文标题】:c# MouseWheel Scroll and RTB VScroll Event 【发布时间】:2011-12-05 18:45:52 【问题描述】:我有点困惑:
如果用户向上滚动,我们有一个聊天应用程序要求不滚动聊天;我们有一个 scrollInfo 类,它为我们提供了检查滚动条拇指是否位于滚动条底部的能力,以便我们确定是否应该滚动。
不幸的是,滚动聊天有很多不同的方式。可以使用向上/向下滚动条框,或滚动条拇指,或者只使用鼠标滚轮滚动。
但是,如果使用向上/向下箭头,我们没有问题。
而且,如果使用滚动条拇指,VScroll 事件确实会触发,但我们无法确定拇指移动到哪个方向,或者如何检查它是否被按住,而不使用计时器不断查询鼠标左键状态。
最后,如果鼠标滚轮被滚动,虽然我们可以通过查看Delta
属性来判断它的方向,但在处理鼠标滚轮事件后,VScroll
事件仍然会触发。所以,我们基本上发生了重复滚动。
我需要一些帮助。我们的聊天应用如下:
.NET 4.0 Windows 窗体 C# 应用程序 内置于 Visual Studio 2010 *聊天输出:*RichTextBox
自动格式化输入的文本。
这是我们的逻辑的一个示例,但它不起作用:
用户使用鼠标滚轮向上滚动:当新消息进入时,他们不应向下滚动聊天输出框。相反,当滚动事件发生时,它应该能够检测到滚动拇指的位置,并做出决定。
用户使用 ScrollBar thumb 向上滚动:触发 VScroll 事件,该事件检查滚动条是否位于滚动框的“底部”。并且,如果是,它会执行完整滚动事件,以确保插入符号始终放置在滚动框的末尾,并且是隐藏的(因此 READ ONLY 聊天输出,没有实际闪烁的 I 光束)。
用户使用滚动条上/下箭头滚动:工作正常。 (无需解释,因为它已经在工作了)。
我需要在这里澄清一下,我怎样才能正确检查这些事件?
-------- 编辑澄清 ---------
scrollInfo
类的内容:
internal class Scrollinfo
internal 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(Control rtb, int postion)
var info = new Scrollbarinfo();
info.CbSize = Marshal.SizeOf(info);
var chk = GetScrollBarInfo(rtb.Handle,
ObjidVscroll,
ref info);
if (chk == 0)
GetScrollBarInfo(rtb.Handle,
ObjidVscroll,
ref info);
bool isbottom = info.XyThumbBottom
>= (info.RcScrollBar.Bottom - info.RcScrollBar.Top - (info.DxyLineButton + 1));
if (info.DxyLineButton <= 0) isbottom = true;
if (info.XyThumbBottom <= 0) isbottom = true;
return isbottom;
internal struct Scrollbarinfo
internal int CbSize;
internal Rect RcScrollBar;
internal int DxyLineButton;
internal int XyThumbTop;
internal int XyThumbBottom;
internal int Reserved;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 6)]
internal int[] Rgstate;
internal struct Rect
internal int Left;
internal int Top;
internal int Right;
internal int Bottom;
【问题讨论】:
同样让我们感到困惑的是,如果用户使用鼠标滚轮向上滚动,VScroll
事件会按预期触发,但它仍会记录滚动拇指位于底部;而不是注册它已向上滚动。我认为这样做是因为VScroll
没有在事件之后触发,而是在事件期间触发,并且滚动拇指还没有改变位置。因此,我们遇到了滚动问题。
您在谈论“scrollinfo”类而没有解释它的作用。听起来像是坏了。在 VScroll 事件中使用 GetCharIndexFromPosition 和 GetLineFromCharIndex 来找出用户正在看到的内容。
我添加了scrollinfo
的内容,这样你就可以看到它的作用了。
【参考方案1】:
你可以试试这样的:
使用要显示的新文本更新框,然后使用以下代码找到最后一个可见行:
rtb.GetLineFromCharIndex(rtb.GetCharIndexFromPosition(新点(rtb.Width, rtb.Height)));现在下次您需要将文本放入 RichTextBox 时,只需使用与上述相同的代码检查最后一个可见行。
如果新的最后可见行小于旧行,则表示用户向上滚动(或 RichTextBox 已调整大小)。无论哪种情况,您只需将插入符号移到文本末尾,然后调用RichTextBox.ScrollToCaret()
方法即可恢复位置。
我还建议您查看 MSDN 网站上的以下内容:
RichTextBox Methods RichTextBox.GetCharIndexFromPosition Method RichTextBox.GetLineFromCharIndex Method RichTextBox.Select Method¹ RichTextBox.ScrollToCaret Method¹这可用于设置插入符号的位置。
【讨论】:
非常感谢,这是最有意义的。你得到了赏金:)以上是关于c# MouseWheel Scroll 和 RTB VScroll 事件的主要内容,如果未能解决你的问题,请参考以下文章
Added non-passive event listener to a scroll-blocking 'mousewheel' event. Consider marking e
使用 MouseWheel c# winform 图表水平滚动
使用带有滚动条的任何控件时不会触发 MouseWheel 事件(在 C# Windows 窗体中)