delphi TListView列标题定义颜色-如何为标题栏中未使用的空间着色

zlwx9yxi  于 2022-11-04  发布在  其他
关注(0)|答案(1)|浏览(162)

我需要在 Delphi 的列表视图与彩色列标题。使用VCL样式不是选项。
检查完两个主题后:

我已经定义了绘制彩色列标题的TMyListView。
我的问题是:我不知道如何在最后一列后绘制相同的颜色(最后一列的右边框和ListView右侧之间的空间)。
下面是用我的TMyListView进行的小测试:

unit Unit1;

interface

uses
  Winapi.Windows, Winapi.Messages, Winapi.CommCtrl,
  System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.ComCtrls;

 type
    TMyListView = class(TCustomListView)
       private
          FHeaderHandle: HWND;
          FHeaderColor: TColor;
          FHeaderFontColor: TColor;

          function WMNotifyHeaderDraw(var AMessage: TWMNotify): boolean;
       protected
          procedure CreateWnd; override;
          Procedure WMNotify(var Msg: TWMNotify); message WM_NOTIFY;

       public
          constructor Create(AOwner: TComponent); override;
          destructor Destroy; override;

    end;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { Private declarations }
    FMyListView: TMyListView;

    procedure CreateMyListView();
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

//------------------ TMyListView-----------------

constructor TMyListView.Create(AOwner: TComponent);
begin
  inherited Create(AOwner);

  FHeaderColor := clOlive;
  FHeaderFontColor:= clYellow;

end;

procedure TMyListView.CreateWnd;
begin
  inherited;

  FHeaderHandle := GetWindow(handle, GW_CHILD);
end;

destructor TMyListView.Destroy;
begin

  inherited Destroy;
end;

procedure TMyListView.WMNotify(var msg: TWMNotify);
begin

  if (FHeaderColor <> clNone)  then
  begin
     if WMNotifyHeaderDraw(msg) then exit;
  end;

  inherited;

end;

function TMyListView.WMNotifyHeaderDraw(var AMessage: TWMNotify): boolean;
const
  DT_ALIGN: array[TAlignment] of integer = (DT_LEFT, DT_RIGHT, DT_CENTER);
var
  fontColor: TColor;
  NMCustomDraw: TNMLVCustomDraw;
  b: TBrush;
  hitemRect: TRect;
  columnIndex: integer;
  columnCaption: string;

begin

  result := false;

  if (AMessage.NMHdr.hwndFrom = FHeaderHandle) and
     (AMessage.NMHdr.code = NM_CUSTOMDRAW)  then
  begin
    result := true;
    NMCustomDraw := PNMLVCustomDraw(TMessage(AMessage).LParam)^;
    case NMCustomDraw.nmcd.dwDrawStage of

      CDDS_PREPAINT:
      begin

        AMessage.Result := CDRF_NOTIFYITEMDRAW;

      end;

      CDDS_ITEMPREPAINT:
      begin
          fontColor := Font.Color;
          b := TBrush.Create;
          try
             hitemRect := NMCustomDraw.nmcd.rc;
             columnIndex := NMCustomDraw.nmcd.dwItemSpec;
             SelectObject(NMCustomDraw.nmcd.hdc, b.Handle);
             b.Color := clLtGray;        // separator
             FillRect(NMCustomDraw.nmcd.hdc, Rect(hitemRect.Right-1, hitemRect.Top, hitemRect.Right, hitemRect.Bottom), b.Handle);
             b.Color := FHeaderColor;   // header background
             FillRect(NMCustomDraw.nmcd.hdc, Rect(hitemRect.Left, hitemRect.Top, hitemRect.Right-1, hitemRect.Bottom), b.Handle);
          finally
             b.Free;
          end;
          if FHeaderFontColor <> clNone then
             fontColor := FHeaderFontColor;

          SetTextColor(NMCustomDraw.nmcd.hdc, ColorToRGB(fontColor));
          SetBKMode(NMCustomDraw.nmcd.hdc, TRANSPARENT);

          Inc(hitemRect.Left,4);
          Dec(hitemRect.Right,4);
          if self.Column[columnIndex].Alignment = taLeftJustify then Inc(hitemRect.Left,6)
          else Dec(hitemRect.Right,6);

          columnCaption := self.Column[columnIndex].Caption;

          DrawTextW(NMCustomDraw.nmcd.hdc, pWideChar(columnCaption),
                    length(columnCaption), hitemRect,
                    DT_SINGLELINE or DT_ALIGN[self.Column[columnIndex].Alignment] or
                    DT_VCENTER or DT_END_ELLIPSIS);

        AMessage.Result := CDRF_SKIPDEFAULT;

      end;
    else
      AMessage.Result := CDRF_DODEFAULT;
    end;

  end;

end;

//----------------- TForm1-------------------------------------

procedure TForm1.FormCreate(Sender: TObject);
begin
  CreateMyListView();
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FreeAndNil(FMyListView);
end;

procedure TForm1.CreateMyListView();
var cl: TListColumn;
begin
  if not Assigned(FMyListView) then begin
    FMyListView := TMyListView.Create(self);
    FMyListView.Parent := self;
    FMyListView.Align := alClient;
    FMyListView.ViewStyle := vsReport;
    FMyListView.DoubleBuffered := true;

    cl := FMyListView.Columns.Add();
    cl.Caption := 'Column 1';
    cl.Width := 200;
    cl.Alignment := taLeftJustify;
    cl.Tag := 0;

    cl := FMyListView.Columns.Add();
    cl.Caption := 'column 2';
    cl.Width := 250;
    cl.Alignment := taLeftJustify;
    cl.Tag := 1;

    cl := FMyListView.Columns.Add();
    cl.Caption := 'column 3';
    cl.Width := 150;
    cl.Alignment := taRightJustify;
    cl.Tag := 2;

    FMyListView.RowSelect := true;
    //FMyListView.FullDrag := true;

    FMyListView.Items.Add.Caption := 'Item1';
    FMyListView.Items.Add.Caption := 'Item2';
    FMyListView.Items[0].SubItems.Add('11-22');
    FMyListView.Items[0].SubItems.Add('11-33');
    FMyListView.Items[1].SubItems.Add('2222-22');
    FMyListView.Items[1].SubItems.Add('2222-33');

  end;

end;

end.

有人能帮我解决这个问题吗?
多谢了。

2w3kk1z5

2w3kk1z51#

在最后一列后添加一个额外的列:

cl := FMyListView.Columns.Add();
cl.AutoSize := True;

cl.AutoSize属性使滚动条跟随ListView列和其他列的宽度,但不强制滚动条出现,除非固定大小的列开始收缩。
有一个小的缺点,如果你显示行线,它们也会显示在额外的列中,但这在你的例子中不是问题。

相关问题