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:
Delphi-Quellcode:
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.