繁体   English   中英

如何有选择地使Owner Drawn TListBox的画布无效?

[英]How to selectively invalidate Owner Drawn TListBox's canvas?

我有一个所有者绘制TListBox(lbVirtualOwnerDraw),其内容得到动态更新(一秒钟内可以有多达10个更新)。 一次最多可以在列表框中放置300个项目。 每个项目可能有大约5行文本和与之关联的图像。 每当刷新一个项目时,我都必须刷新(或使其无效)TListBox,以便VCL框架调用ListBoxDrawItem。 但由于所有冗余重新涂漆,这会对整体性能产生不利影响。 所以我的问题是:

  1. 有没有办法只使画布的一小部分无效,其中包含一个项目或其中一个部分的图纸? (例如,包含一行文本或位图的矩形)。

  2. 我们如何在Draw Item中处理这样一个选择性的无效矩形? 如果可以将整数作为Refresh或invalidate的一部分传递,我可以在DrawItem中使用它来确定要刷新的内容。

  3. 有没有办法找到一个项目在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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM