我有TListView的后代,它提供了一些额外的功能,例如排序和从TDataset加载自身的能力。我现在希望进一步扩展这个组件,以便在项目添加到列表视图时指定图形的某些方面。
我无法确定要覆盖哪些程序或程序来控制图纸。我已重写DrawItem以更改字体样式以包含删除线,然后调用继承的DrawItem。如果我还指定样式LVS_OWNERDRAWFIXED(在重写的CreateParams()中),我的函数被调用并按我的意思工作,除了只绘制项而不是子项。
有谁知道如何告诉列表视图也可以绘制子项目?我已经找到了one example一个大幅增强的列表视图,但是这个没有足够好的文档记录让我能够完全按照正在发生的事情进行操作,并且我希望不必勾选很多事件和窗口像这样的消息 - 在我看来,简单地设置画布笔,画笔和字体然后让项目绘制本身应该不那么复杂。
这是我到目前为止所拥有的:
protected
procedure CreateParams(var Params: TCreateParams); override;
procedure DrawItem(Item: TListItem; Rect: TRect; State: TOwnerDrawState); override;
procedure TLookupListView.CreateParams(var Params: TCreateParams);
begin
inherited CreateParams(Params);
Params.Style := Params.Style or lvs_OwnerDrawFixed;
end;
procedure TLookupListView.DrawItem(Item: TListItem; Rect: TRect; State: TOwnerDrawState);
var I: Integer;
Left: Integer;
begin
Canvas.Font.Style := Canvas.Font.Style + [fsStrikeOut];
inherited DrawItem(Item, Rect, State);
//I know the canvas must be restored here, this is just for proof-of-concept.
end;
请注意:我对使用提供的事件在TListView的特定实例中进行自定义绘图不感兴趣。我知道该怎么做。我正在尝试将此功能“烘焙”到我的自定义TListview后代组件中。
答案 0 :(得分:2)
组件有一个虚方法IsCustomDrawn()
,调用它来确定需要执行哪些代码路径。在基类实现中,它检查是否分配了绘制子项的任何事件处理程序,但是您可以覆盖该方法以返回要处理的所有绘制阶段的True
,即使没有分配事件处理程序也是如此
如果你想处理代码中的所有内容,你应该覆盖CustomDrawItem()
和CustomDrawSubItem()
并在那里做所有事情。为了使一切工作正常,我将使用调试DCU构建应用程序,从事件处理程序步入并查看可以使用的最小代码量。签出的重要方法是TCustomListView.CNNotify()
- 这里处理所有者绘图的Windows消息。
修改强>
我忘了添加你应该尝试不让所有者在控件中绘制文本,而只是在各个绘制阶段设置画布属性 - 原因是否则你必须确保文本输出是像素 - 在所有Windows版本中都是完美的,这是VCL无法实现的。您可以通过向列表视图添加一些列和行并在设计时切换OwnerDraw
属性来查看此内容,文本会跳转。
答案 1 :(得分:1)
您使用的是哪个版本的Delphi?在Delphi 2007中,TListView通过处理NM_CUSTOMDRAW消息支持自定义绘制,如here所述。 TListView已经为自定义绘图子项定义了事件,以及您可以在后代中覆盖的虚拟方法。