Dav*_*nan 14 delphi delphi-xe2
我正在尝试TListView根据NGLN对另一个SO问题的答案在Delphi中自定义绘制进度条.除了使用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.
Run Code Online (Sandbox Code Playgroud)
表格文件
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
Run Code Online (Sandbox Code Playgroud)
Ser*_*yuz 13
这是针对有缺陷行为的解决方法,而不是如果VCL中存在错误以及一些想法而回答问题.
解决方法是在执行自定义绘图后,将项目绘制cyle的公共控件指定的设备上下文的背景模式设置为透明:
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, Item.Index, SubItem, LVIR_BOUNDS, @R);
Sender.Canvas.MoveTo(R.Left, R.Top);
Sender.Canvas.LineTo(R.Right-1, R.Bottom-1);
SetBkMode(Sender.Canvas.Handle, TRANSPARENT); // <- will effect the next [sub]item
end;
Run Code Online (Sandbox Code Playgroud)
在[子]项目绘制周期中,绘画总是以自上而下的方式完成,具有较低索引的项目在具有较高索引的项目NM_CUSTOMDRAW之前被发送通知.当鼠标从一行移动到另一行时,需要重新绘制两行 - 一行失去热状态,另一行获得它.看起来,当自定义绘图生效时,绘制失去热状态的行会使DC处于不合需要的状态.向上移动鼠标时不会出现问题,因为该项目最后被绘制.
自定义绘图ListView和TreeView控件与自定义绘制其他控件不同,有些复杂(请参阅:使用列表视图和树视图控件自定义绘制).但是你可以完全控制整个过程.在该代码NM_CUSTOMDRAW的情况下,TCustomListView.CNNotify在VCL的"comctrls.pas"是同样复杂.但是,尽管提供了一堆自定义绘图处理程序(其中一半是高级的),但您无法控制VCL的功能.例如,你无法返回CDRF_xxx你想要的,或者你无法设置clrTextBk你想要的.我的偏见是,在Delphi列表视图控件中存在一个错误/设计问题,但在找到解决方法时,我没有比直觉更具体的内容.