我需要在 Delphi 的列表视图与彩色列标题。使用VCL样式不是选项。
检查完两个主题后:
- Change background color of TListView header in older Delphi
- Delphi: ListView (vsReport) single column header caption with custom font color?
我已经定义了绘制彩色列标题的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.
有人能帮我解决这个问题吗?
多谢了。
1条答案
按热度按时间2w3kk1z51#
在最后一列后添加一个额外的列:
cl.AutoSize
属性使滚动条跟随ListView
列和其他列的宽度,但不强制滚动条出现,除非固定大小的列开始收缩。有一个小的缺点,如果你显示行线,它们也会显示在额外的列中,但这在你的例子中不是问题。