You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Delphi中TListView自定义列标题颜色:如何填充标题栏空白区域

Delphi TListView 列标题右侧空白区域上色解决方案

问题核心:自定义TMyListView实现列标题上色后,最后一列右侧至ListView右边界的标题栏空白区域未被填充对应颜色,可通过处理Header控件的自定义绘制消息,在绘制阶段补填空白区域。

具体实现代码

type
  TMyListView = class(TListView)
  private
    FHeaderBrush: TBrush;
    procedure WMNotify(var Message: TWMNotify); message WM_NOTIFY;
  protected
    procedure CreateParams(var Params: TCreateParams); override;
  public
    constructor Create(AOwner: TComponent); override;
    destructor Destroy; override;
  end;

constructor TMyListView.Create(AOwner: TComponent);
begin
  inherited;
  FHeaderBrush := TBrush.Create;
  FHeaderBrush.Color := clSkyBlue; // 替换为你的自定义标题颜色
end;

destructor TMyListView.Destroy;
begin
  FHeaderBrush.Free;
  inherited;
end;

procedure TMyListView.CreateParams(var Params: TCreateParams);
begin
  inherited;
  // 启用自定义绘制通知
  Params.Style := Params.Style or LVS_OWNERDRAWFIXED;
end;

procedure TMyListView.WMNotify(var Message: TWMNotify);
var
  pNMHDR: PNMHDR;
  pNMCustomDraw: PNMCustomDraw;
  HeaderRect: TRect;
  ColumnCount: Integer;
  LastColumnRight: Integer;
begin
  inherited;
  pNMHDR := Message.NMHdr;
  // 仅处理Header控件的自定义绘制消息
  if (pNMHDR^.code = NM_CUSTOMDRAW) and (pNMHDR^.hwndFrom = HeaderHandle) then
  begin
    pNMCustomDraw := PNMCustomDraw(pNMHDR);
    case pNMCustomDraw^.dwDrawStage of
      CDDS_PREPAINT:
        Message.Result := CDRF_NOTIFYITEMDRAW; // 通知绘制每个列项
      CDDS_ITEMPREPAINT:
        begin
          // 绘制单个列标题背景
          SetDCBrushColor(pNMCustomDraw^.hdc, ColorToRGB(FHeaderBrush.Color));
          FillRect(pNMCustomDraw^.hdc, pNMCustomDraw^.rc, FHeaderBrush.Handle);
          // 绘制列标题文字(可自定义文字颜色、对齐方式)
          SetTextColor(pNMCustomDraw^.hdc, clBlack);
          SetBkMode(pNMCustomDraw^.hdc, TRANSPARENT);
          DrawText(pNMCustomDraw^.hdc, PChar(Columns[pNMCustomDraw^.dwItemSpec].Caption),
            -1, pNMCustomDraw^.rc, DT_SINGLELINE or DT_VCENTER or DT_LEFT or DT_END_ELLIPSIS);
          Message.Result := CDRF_SKIPDEFAULT; // 跳过默认绘制
        end;
      CDDS_POSTPAINT:
        begin
          // 填充最后一列右侧的空白区域
          GetClientRect(HeaderHandle, HeaderRect);
          ColumnCount := Columns.Count;
          if ColumnCount > 0 then
          begin
            LastColumnRight := 0;
            // 计算所有列的总宽度(应对列宽调整场景)
            for var I := 0 to ColumnCount - 1 do
              Inc(LastColumnRight, Columns[I].Width);
            HeaderRect.Left := LastColumnRight;
            if HeaderRect.Left < HeaderRect.Right then
            begin
              SetDCBrushColor(pNMCustomDraw^.hdc, ColorToRGB(FHeaderBrush.Color));
              FillRect(pNMCustomDraw^.hdc, HeaderRect, FHeaderBrush.Handle);
            end;
          end
          else
          begin
            // 无列时填充整个Header区域
            SetDCBrushColor(pNMCustomDraw^.hdc, ColorToRGB(FHeaderBrush.Color));
            FillRect(pNMCustomDraw^.hdc, HeaderRect, FHeaderBrush.Handle);
          end;
        end;
    end;
  end;
end;

关键说明

  1. Header控件消息拦截:通过WM_NOTIFY消息捕获Header控件的NM_CUSTOMDRAW事件,分阶段处理绘制逻辑。
  2. 空白区域计算:在CDDS_POSTPAINT阶段,计算所有列的总宽度,对比Header控件的客户区右边界,确定空白区域范围后填充颜色。
  3. 自适应列宽变化:每次绘制时重新计算列总宽度,确保列宽调整后空白区域仍能正确填充。

内容的提问来源于stack exchange,提问作者Eric

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 00:02:25