使用自定义绘图时,Delphi 列表视图控件是否存在错误? [英] Is there a bug in the Delphi list view control when using custom drawing?
问题描述
).但是您可以完全控制整个过程.VCL的'comctrls.pas'中TCustomListView.CNNotify
的NM_CUSTOMDRAW
案例中的代码同样复杂.但是,尽管提供了一堆自定义绘图处理程序(其中一半是高级),但您无法控制 VCL 的功能.例如,你不能返回你想要的 CDRF_xxx
或者你不能设置你想要的 clrTextBk
.我有偏见的观点是,Delphi 列表视图控件中存在错误/设计问题,但我没有什么比寻找解决方法更具体的直觉了.
I'm trying to custom draw a progress bar in a Delphi TListView
as suggested by NGLN's answer to another SO question. This works fine, apart from the interaction with hot tracking when drawn using the new explorer theme introduced in Vista.
The hot tracking painting and the Delphi custom drawing events appear to interfere with each other. For example, the sort of output I am seeing looks like this:
The text in Column 1 should read Item 3 but is obliterated. It looks like a bug in the Delphi wrapper to the list view control, but it could equally be that I'm doing something wrong!
Although I've been developing this in XE2, the same behaviour occurs in 2010 and, presumably, XE.
Here's the code to reproduce this behaviour:
Pascal file
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.
Form file
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
This is a workaround for the defective behavior rather than being an answer to the question if there's a bug in the VCL, and a few thoughts.
The workaround is to set the background mode of the device context assigned by the common control for item painting cyle to transparent after carrying out custom drawing:
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;
In an [sub]item paint cycle, the painting is always done in a top-down fashion, items having a lower index are sent NM_CUSTOMDRAW
notification prior to ones with higher indexes. When the mouse is moved from one row to another, two rows need to be re-drawn - the one loosing the hot state, and the one gaining it. It would seem, when custom drawing is in-effect, drawing the row that's loosing the hot-state leaves the DC in an undesirable state. This is not a problem when moving the mouse upwards, because that item gets drawn last.
Custom drawing ListView and TreeView controls are different than custom drawing other controls and somewhat complicated (see: Custom Draw With List-View and Tree-View Controls). But you have full control over the entire process. The code in the NM_CUSTOMDRAW
case of TCustomListView.CNNotify
in 'comctrls.pas' of the VCL is equally complicated. But despite being provided a bunch of custom drawing handlers (half of them being advanced), you have no control over what the VCL does. For instance you can't return the CDRF_xxx
you'd like or you can't set the clrTextBk
you want. My biased opinion is that, there's a bug/design issue in the Delphi list view control, but I have nothing more concrete than an intuition as in finding a workaround.
这篇关于使用自定义绘图时,Delphi 列表视图控件是否存在错误?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!