In a 32-bit VCL Application in Windows 10 in Delphi 11 Alexandria, I need to repaint a whole TListView
column while resizing the column. The ListView items and subitems are being displayed with ListView.OwnerDraw
.
So I subclassed the ListView to be notified when the column resizes:
TListView = class(Vcl.ComCtrls.TListView)
private
FHeaderHandle: HWND;
procedure WMNotify(var AMessage: TWMNotify); message WM_NOTIFY;
protected
procedure CreateWnd; override;
...
procedure TListView.CreateWnd;
begin
inherited;
FHeaderHandle := ListView_GetHeader(Handle);
end;
procedure TListView.WMNotify(var AMessage: TWMNotify);
begin
if (AMessage.NMHdr.hwndFrom = FHeaderHandle) and ((AMessage.NMHdr.code = HDN_ENDTRACK) or (AMessage.NMHdr.code = HDN_TRACK)) then
begin
TMessage(AMessage).Result := 0;
InvalidateRect(FHeaderHandle, nil, true);
CodeSite.Send('TListView.WMNotify: HDN_ENDTRACK');
end
else
inherited;
end;
Unfortunately, it reacts only at the END of column resizing, and not WHILE resizing the column! Also, the column is not repainted!
The issue with HDN_TRACK
not being delivered is well known. A solution is to look for HDN_ITEMCHANGING
instead.
Regarding the repainting issue, notice that you do
InvalidateRect(FHeaderHandle, nil, true);
This requests a repaint of the list view header. The header is a separate window, a header control, which occupies the top row of your list view and contains only the column captions.
You want to invalidate not the header, but the actual column in the list view.
Just invalidate the entire list view.