[英]How to selectively invalidate Owner Drawn TListBox's canvas?
我有一个所有者绘制TListBox(lbVirtualOwnerDraw),其内容得到动态更新(一秒钟内可以有多达10个更新)。 一次最多可以在列表框中放置300个项目。 每个项目可能有大约5行文本和与之关联的图像。 每当刷新一个项目时,我都必须刷新(或使其无效)TListBox,以便VCL框架调用ListBoxDrawItem。 但由于所有冗余重新涂漆,这会对整体性能产生不利影响。 所以我的问题是:
有没有办法只使画布的一小部分无效,其中包含一个项目或其中一个部分的图纸? (例如,包含一行文本或位图的矩形)。
我们如何在Draw Item中处理这样一个选择性的无效矩形? 如果可以将整数作为Refresh或invalidate的一部分传递,我可以在DrawItem中使用它来确定要刷新的内容。
有没有办法找到一个项目在TListBox上是否可见(按索引)?
提前致谢!
您可以使用InvalidateRect
api使窗口的一部分无效。 要查找项占用的区域,可以使用ListBox的ItemRect
方法。 例如,使第4项无效:
var
R: TRect;
begin
R := ListBox1.ItemRect(3);
InvalidateRect(ListBox1.Handle, @R, True);
end;
(或'False'为'InvalidateRect'的'bErase',请参阅其文档)。 要使位图或文本无效,请在传递给InvalidateRect之前相应地修改矩形。
您无法传递索引或任何类型的用户数据来刷新或无效。 在绘画例程中,您必须根据位置确定要绘制的项目,或者如果绝对必要则使用全局变量。 但是你不需要它,如果你只使一个项目的一部分无效, OnDrawItem
只会被调用那个项目。 在任何情况下,不要过于担心绘制非无效项目,因为在更新区域之外不会有任何实际绘图,您将不会有任何重大的性能损失(请参阅此处的第3段)。
要确定某个项目是否可见,您将从顶部的第一个可见项目开始,并将连续项目的高度添加到控件的ClientHeight。 顶部项目位于TopIndex
。 如果项目的高度是固定的,您已经知道最多可以看到多少项目。 如果不是,你需要总结它们。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.