QC#101189
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
I don't have a clue for the black rectangle at the text position, but the missing hot tracking is due to the DefaultDraw := False; in your code. OnCustomDrawSubItem is only called for subitem <> 0, so the first column is drawn as default while the second uses your code. Custom drawing of the first column can be made with OnCustomDrawItem.
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.