如何在调整列大小时重新绘制 TListView 列?

How to repaint a TListView column while resizing the column?

在 Windows 10 in Delphi 11 Alexandria 中的 32 位 VCL 应用程序中,我需要在调整列大小时重新绘制整个 TListView 列。 ListView 项目和子项目显示为 ListView.OwnerDraw

所以我将 ListView 子类化为在列调整大小时收到通知:

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;

不幸的是,它仅在调整列大小时结束时做出反应,而不是在调整列大小时时!另外,该列未重新绘制!

HDN_TRACK 未交付的问题 is well known。一个解决方案是寻找 HDN_ITEMCHANGING 代替。

关于重绘的问题,注意你有

InvalidateRect(FHeaderHandle, nil, true);

这要求重新绘制 列表视图 header。 header 是一个单独的 window,一个 header control,它占据列表视图的顶行并且仅包含列标题。

您不想使 header 无效,而是要使列表视图中的实际列无效。

只是使整个列表视图无效。