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;