我有一个Delphi 6应用程序与TListBox控件设置为lbOwnerDrawVariable。在运行时,我将一个字符串添加到列表框中。我有OnMeasureItem()和OnDrawItem()的事件处理程序,我在每个事件处理程序的第一行代码上设置了断点。然而,它们都没有被调用过。一次也没有。即使我在列表框上执行Explicit Refresh或Repaint调用也不行。
这真的是基本的东西,所以它是什么,我做错了,可以抑制这些事件处理程序的调用,并随后扰乱我的所有者绘制代码?单个字符串正确地显示在列表框中。我加入了一个OnClick()事件处理程序,只是为了看看它是否有效。
OnMeasureItem
和OnDrawItem
事件是响应来自Windows的WM_MEASUREITEM
和WM_DRAWITEM
消息(间接)触发的。确保你的应用程序中没有任何消息处理程序过滤掉该消息,或者VCL的内部CN_MEASUREITEM
和CN_DRAWITEM
消息。
原来问题是由于我正在使用的TListBox的Columns属性中的非零值。在转换为owner-draw并离开TListBox之前,我已经尝试过使用列。属性的非零值。显然,非零Columns属性值会抑制触发与所有者绘制相关的事件触发。一旦我把这个属性设置回0,OnMeasureItem()和OnDrawItem()就开始发射了
这里真的很少会出错。如果你设置一个测试应用来尝试这个,那么它的功能就像你所期望的那样,事件处理程序被调用。
您报告的行为最可能的原因是如果在分配事件处理程序之前添加了项。如果在设计时将项目添加到.dfm文件中,则通常会发生这种情况。你说你在运行时添加项目。也许在分配事件处理程序之前,您添加它们的速度太快了。如果您为响应事件(例如按钮单击)添加项会发生什么?请尝试一下,因为您可以确定事件处理程序是由该点分配的。
如果这没有帮助,那么显然你的应用程序中有一些代码干扰了VCL代码。
我有同样的问题:我的OnDrawItem事件处理程序没有被调用,如果列属性是非零。原来这是因为Style属性被设置为lbOwnerDrawVariable。可变的项目高度不允许与多列结合使用,可能是因为如果允许不同的项目高度,则行不会跨列排列。一旦Style属性被设置为lbOwnerDrawFixed, OnDrawItem事件处理程序就会像预期的那样被调用。
我有一个类似的问题与csonerdrawvariable样式的组合框不触发OnMeasureItem事件。正如David Heffernan所建议的那样,问题在于这些项目是在设计时添加到列表中的。我最终使用的解决方法是向FormCreate事件处理程序添加代码,将设计时列表复制到临时变量中,然后清除列表并将项目添加回来。拙劣但有效。