Search code examples
windowslistviewdelphicolumnheader

Change background color of TListView header in older Delphi


An old app using Delphi 7, but should be similar code in older Delphi versions up to perhaps 2010. I need to change the background color of a TListView header so I can offer a dark theme. I can change the colors of everything else. I found the thread below which apparently works for changing the font color on a column header, but I need to adjust the background color of the entire header as well.

Delphi: ListView (vsReport) single column header caption with custom font color?

Can someone please help as I am lost. Windows message notifications are beyond my comprehension.

Many thanks.


Solution

  • I'm fairly proud of myself and somehow found bits and pieces of code that all went together to make it all work. Something like this...

    procedure TTntListView.WMNotify(var AMessage: TWMNotify);
    const
      DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
    var
      NMCustomDraw: TNMCustomDraw;
      i: Integer;
      r: TRect;
    begin
      if (AMessage.NMHdr.hwndFrom = FHeaderHandle) and
        (AMessage.NMHdr.code = NM_CUSTOMDRAW) then
      begin
        NMCustomDraw := PNMCustomDraw(TMessage(AMessage).LParam)^;
        case NMCustomDraw.dwDrawStage of
          CDDS_PREPAINT: AMessage.Result := CDRF_NOTIFYITEMDRAW;
          CDDS_ITEMPREPAINT: begin
            i := NMCustomDraw.dwItemSpec;
            r := NMCustomDraw.rc;
            FillRect(NMCustomDraw.hdc, r, Sender.Canvas.Brush.Handle);
            SetBkColor(NMCustomDraw.hdc,  ColorToRGB(Sender.Canvas.Brush.Color));
            SetTextColor(NMCustomDraw.hdc, ColorToRGB(Sender.Canvas.Font.Color));
            DrawEdge(NMCustomDraw.hdc,r,EDGE_SUNKEN,BF_LEFT);
            Inc(r.Left,2);
            Dec(r.Right,2);
            if Sender.Column[i].Alignment = taLeftJustify then Inc(r.Left,3)
            else Dec(r.Right,3);
            DrawTextW(NMCustomDraw.hdc,
              pWideChar(Sender.Column[i].Caption),
              length(Sender.Column[i].Caption),
              r,
              DT_SINGLELINE or DT_ALIGN[Sender.Column[i].Alignment] or
                DT_VCENTER or DT_END_ELLIPSIS);
            Message.Result := CDRF_SKIPDEFAULT;
          end;
          else AMessage.Result := CDRF_DODEFAULT;
        end;
      end
      else inherited;
    end;