如何摆脱TListBox垂直滚动限制?
我已经使用 TListBox 实现了 日志查看器 在虚拟模式。
它工作正常(对于我编写的所有代码),按预期显示内容(我什至轻松添加了水平滚动条),但我想我已经达到了垂直滚动条的某种限制。
也就是说,当我从上到下滚动垂直条时,它不会将内容滚动到列表的末尾,而只会滚动到某个限制。
你知道有什么办法可以摆脱这个限制吗?我尝试使用 SetScrollInfo
,但它不起作用,因为限制听起来不在滚动条中,而是在 TListBox
本身中。
我知道创建专用 TCustomControl
的解决方案:在这种情况下,SetScrollInfo
将按预期工作。但是有人知道仍然使用 TListBox 的解决方案/技巧吗?
编辑:说清楚 - 我不要求(第三方)组件解决方案,但要知道是否有一些低级 GDI 消息发送到标准 TListBox
来覆盖此限制。如果没有,我将使用专用的 TCustomControl
解决方案。
下面是使用 TSCROLLINFO 的代码:
procedure ScrollVertHuge(Handle: HWND; count: integer);
var Scroll: TSCROLLINFO;
begin
Scroll.cbSize:= sizeof(Scroll);
Scroll.fMask := SIF_DISABLENOSCROLL or SIF_RANGE;
Scroll.nMin := 0;
Scroll.nMax := count;
SetScrollInfo(Handle,SB_VERT,Scroll,false);
end;
准确地说: 当然,添加和绘制都可以工作(我的工具按预期工作),但不起作用的是垂直滚动条拖动。我重命名了问题的标题,并删除了已弃用的 MSDN 文章,这些文章令人困惑。
I've implement a log viewer using a TListBox
in virtual mode.
It works fine (for all the code I wrote), displays the content as expected (I even added an horizontal scrollbar easily), but I guess I've reached the some kind of limit of the vertical scrollbar.
That is, when I scroll the vertical bar from the top to the bottom, it will not scroll the content to the end of the list, but only to some limit.
Do you know any possibility to get rid of this limit? I tried with SetScrollInfo
, but it didn't work since the limit sounds to be not in the scrollbar, but in the TListBox
itself.
I know the solution of creating a dedicated TCustomControl
: in this case, the SetScrollInfo
will work as expected. But does anyone know about a solution/trick to still use TListBox
?
Edit: to make it clear - I don't ask for a (third-party) component solution, but to know if there is some low-level GDI message to send to the standard TListBox
to override this limit. If there is none, I'll go to the dedicated TCustomControl
solution.
Here is the code using TSCROLLINFO:
procedure ScrollVertHuge(Handle: HWND; count: integer);
var Scroll: TSCROLLINFO;
begin
Scroll.cbSize:= sizeof(Scroll);
Scroll.fMask := SIF_DISABLENOSCROLL or SIF_RANGE;
Scroll.nMin := 0;
Scroll.nMax := count;
SetScrollInfo(Handle,SB_VERT,Scroll,false);
end;
To precise the issue: Adding and drawing both work, of course (my tool works as exepected), but what does not work is the vertical scrollbar dragging. I renamed the title of the question, and got rid of the deprecated MSDN articles, which are confusing.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
下面的内容可能应该被视为有缺陷的操作系统行为的解决方法,因为除非启用主题,否则列表框控件的默认窗口过程可以很好地处理拇指跟踪。由于某种原因,当启用主题时(此处测试显示的是 Vista 及更高版本),该控件似乎依赖于
WM_VSCROLL
的 Word 大小的滚动位置数据。首先,一个复制问题的简单项目,下面是一个所有者绘制虚拟 (
lbVirtualOwnerDraw
) 列表框,其中包含约 600,000 个项目(由于项目数据未缓存,因此不需要花一点时间即可填充该框) )。高列表框将有助于轻松跟踪行为:要查看问题,只需用拇指跟踪滚动条,您会注意到项目如何从头开始包装,每 65536 个项目如 Arnaud 在对问题的评论。当您松开拇指时,它将捕捉到顶部
High(Word)
中的项目。下面的解决方法拦截控件上的
WM_VSCROLL
并手动执行拇指和项目定位。为了简单起见,该示例使用插入器类,但任何其他子类方法都可以:The below probably should be considered as a work-around for defective OS behavior, since, unless themes are enabled, the default window procedure of a listbox control handles thumb-tracking quite well. For some reason, when themes are enabled (test here shows with Vista and later), the control seems to rely upon the Word sized scroll position data of
WM_VSCROLL
.First, a simple project to duplicate the problem, below is an owner draw virtual (
lbVirtualOwnerDraw
) list box with some 600,000 items (since item data is not cached it doesn't take a moment to populate the box). A tall listbox will be good for easy following the behavior:To see the problem just thumb-track the scroll bar, you'll notice how the items are wrapped to begin from the start for every 65536 one as described by Arnaud in the comments to the question. And when you release the thumb, it will snap to an item in the top
High(Word)
.Below workaround intercepts
WM_VSCROLL
on the control and performs thumb and item positioning manually. The sample uses an interposer class for simplicity, but any other sub-classing method would do:对于我编写的自定义日志查看器,我在虚拟模式下使用
TListView
,而不是TListBox
。效果很好,没有 32K 限制,根本不需要摆弄SetScrollInfo()
。只需设置Item.Count
,其余的就会自动处理。它甚至还有一个OnDataHint
事件,可让您仅加载TListView
实际需要的数据,从而优化数据访问。使用TListBox
无法实现这一点。For a custom log viewer I wrote, I use a
TListView
in virtual mode, not aTListBox
. Works great, no 32K limits, no need to fiddle withSetScrollInfo()
at all. Just set theItem.Count
and the rest is handled automatically. It even has anOnDataHint
event that can be used to optimize data access by letting you load only the data that theTListView
actually needs. You don't get that with aTListBox
.