使用自定义绘图时,Delphi列表视图控件是否有错误?
QC#101189
我试图自定义在Delphi TListView中绘制一个进度条,如NGLN’s answer to another SO question所示.除了使用Vista中引入的新的资源管理器主题绘制时,与热跟踪的交互作用很好. 热跟踪绘画和Delphi自定义绘图事件似乎互相干扰.例如,我看到的输出类型如下所示: 列1中的文本应该读取项3,但是被删除.它看起来像Delphi包装器中的列表视图控件的错误,但同样可能的是我做错了事情! 虽然我在XE2中一直在开发这个过程,但2010年也是这样,也就是XE. 以下是重现此行为的代码: Pascal文件 unit Unit1; interface uses Windows,Classes,Controls,Forms,CommCtrl,ComCtrls; type TForm1 = class(TForm) ListView: TListView; procedure FormCreate(Sender: TObject); procedure ListViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean); end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.FormCreate(Sender: TObject); begin ListView.RowSelect := True; ListView.Items.Add.Caption := 'Item 1'; ListView.Items.Add.Caption := 'Item 2'; ListView.Items.Add.Caption := 'Item 3'; end; procedure TForm1.ListViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean); var R: TRect; begin DefaultDraw := False; ListView_GetSubItemRect(Sender.Handle,Item.Index,SubItem,LVIR_BOUNDS,@R); Sender.Canvas.MoveTo(R.Left,R.Top); Sender.Canvas.LineTo(R.Right-1,R.Bottom-1); end; end. 表单文件 object Form1: TForm1 Caption = 'Custom Draw List View Bug' ClientHeight = 290 ClientWidth = 554 OnCreate = FormCreate object ListView: TListView Align = alClient Columns = < item Caption = 'Column 1' Width = 250 end item Caption = 'Column 2' Width = 250 end> ViewStyle = vsReport OnCustomDrawSubItem = ListViewCustomDrawSubItem end end 解决方法
这是有缺陷的行为的解决方法,而不是解决问题的答案,如果在VCL有一个错误,以及一些想法.
解决办法是在进行自定义绘图之后,将项目绘画的公共控件分配给设备上下文的背景模式设置为透明: procedure TForm1.ListViewCustomDrawSubItem(Sender: TCustomListView; Item: TListItem; SubItem: Integer; State: TCustomDrawState; var DefaultDraw: Boolean); var R: TRect; begin if not [CustomDrawing] then // <- If we're not gonna do anything do not Exit; // fiddle with the DC in any way DefaultDraw := False; ListView_GetSubItemRect(Sender.Handle,R.Bottom-1); SetBkMode(Sender.Canvas.Handle,TRANSPARENT); // <- will effect the next [sub]item end; 在[子]项目绘画循环中,绘画始终以自顶向下的方式完成,具有较低索引的项目在具有较高索引的项目之前发送NM_CUSTOMDRAW通知.当鼠标从一行移动到另一行时,需要重新绘制两行 – 一个放弃热状态,一个获取它.当自定义绘图有效时,绘制掉热状态的行会使DC处于不良状态.当向上移动鼠标时,这不是问题,因为该项目最后被绘制. 自定义绘图ListView和TreeView控件与自定义绘制其他控件不同,有些复杂(参见:Custom Draw With List-View and Tree-View Controls).但是你可以完全控制整个过程. VCL的“comctrls.pas”中的TC_CANOMDRAW案例TCustomListView.CNNotify中的代码同样复杂.但是尽管提供了一堆自定义绘图处理程序(其中一半是高级的),但是您无法控制VCL的工作.例如,您不能返回您想要的CDRF_xxx,或者您无法设置所需的clrTextBk.我有偏见的是,Delphi列表视图控件中存在一个错误/设计问题,但是我没有比找到解决方法更直观的直觉. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |