Grupos de Google ya no admite nuevas publicaciones ni suscripciones de Usenet. El contenido anterior sigue siendo visible.

TListview owner draw headers

Visto 137 veces
Saltar al primer mensaje no leído

Barry Morris

no leída,
24 abr 2008, 13:04:4424/4/08
a
Hello

I found some code for drawing text and images on headers, but I would like
to go one step further and owner draw the complete header, including the
inaccessible area to the right of the last column. Basically the code below
returns the rect of the text area and not the surrounding 'button' area, and
there is no message for the area to the right of the last column. I have a
handle to the header control if that helps. Incidentally would it also be
possible to owner draw other sub-components of the listview, e.g. the right
and bottom scroll bars?

I think the answer to the header problem is to override the createparams
with something like, however I do not know how to override createparams of
sub components (if that is the correct terminology) of the TListview

with Params do
Style := Style or OWNERDRAW;


TIA

Barry

Here is the code I have, please note that this is based on TntListView as I
also require Unicode functionality.

unit AIStntListview;

interface

uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, TntComCtrls, Commctrl;

type
TAIStntListview = class(TtntListview)
private
{ Private declarations }
fHeaderHandle: HWND;
fOldListViewWP: TWndMethod;
fCurrentsort: integer;
fSortDecending: boolean;
fShowSortArrow: boolean;
fSortToColumn: integer;
fXPStyle: boolean;
fHeaderColor: TColor;
procedure DrawHeader(Index: integer; ARect: TRect;
AState: integer; DC: HDC);
procedure NewListViewWP(var Msg: TMessage);
procedure RefreshHeader;
procedure SetSortToColumn(const Value: integer);
procedure SetShowSortArrow(const Value: boolean);
protected
{ Protected declarations }
procedure ColClick(Column: TListColumn); override;
procedure ColRightClick(Column: TListColumn; Point: TPoint); override;
public
{ Public declarations }
published
{ Published declarations }
Constructor Create(AOwner:TComponent);override;
Destructor Destroy;override;
property OnColumnClick;
property ShowSortArrow: boolean read fShowSortArrow write
SetShowSortArrow default false;
property SortToColumn: integer read fSortToColumn write SetSortToColumn
default -1;
procedure SetSortedColumn(const Column: integer; const Decending:
Boolean);
property XPStyle: boolean read fXPStyle write fXPStyle default false;
property HeaderColor: TColor read fHeaderColor write fHeaderColor;
end;

procedure Register;

implementation

{$R aistntlistview.res}

procedure Register;
begin
RegisterComponents('AIS', [TAIStntListview]);
end;

procedure TAIStntListview.ColClick(Column: TListColumn);
begin
inherited;
if (fSorttocolumn = -1) or (Column.Index <= fSorttocolumn) then
begin
if fCurrentsort = Column.Index then
fSortDecending := fSortDecending xor true
else
fSortDecending := False;
fCurrentsort := Column.Index;
end;
RefreshHeader;
end;

procedure TAIStntListview.ColRightClick(Column: TListColumn;
Point: TPoint);
begin
inherited;
RefreshHeader;
end;

constructor TAIStntListview.Create(AOwner: TComponent);
begin
inherited;
fOldListViewWP := WindowProc;
WindowProc := NewListViewWP;
fSortDecending := false;
fCurrentSort := 0;
fSortToColumn := -1;
fXPStyle := false;
fHeaderColor := clbtnface;
end;

destructor TAIStntListview.Destroy;
begin
WindowProc := fOldListViewWP;
inherited;
end;

procedure TAIStntListview.DrawHeader(Index: integer; ARect: TRect;
AState: integer; DC: HDC);
var
b : TBrush;
p : TPen;
s : string;
tw: integer;
BM, BMM: TBitmap;
r, c: integer;
FTColor: TColor;
HoldRect: TRect;
Brush : THandle;


function TextExtent(const Text: string): TSize;
begin
Result.cX := 0;
Result.cY := 0;
Windows.GetTextExtentPoint32(DC, PChar(Text), Length(Text), Result);
end;

function TextWidth(const Text: string): Integer;
begin
Result := TextExtent(s).cX;
end;

begin
b := TBrush.Create;
p := TPen.Create;
s := Columns[Index].Caption;
BM := TBitmap.Create;
BMM := TBitmap.Create;
HoldRect := ARect;
try
b.Color := fHeaderColor;
HoldRect := ARect;
inflaterect(ARect, 0, -2);
if index = (Columns.Count -1) then
ARect.Right := ARect.Right + (width - ARect.Right);
FillRect(DC, ARect, b.Handle);
ARect := HoldRect;
inc(ARect.Left, 5);
inc(ARect.top, 1);
dec(ARect.Right, 5);
if fShowsortarrow then
begin
if fCurrentsort = Index then
begin
if fSortDecending then
begin
BM.LoadFromResourceName(HInstance, 'SORTDOWNARROW');
end
else
BM.LoadFromResourceName(HInstance, 'SORTUPARROW');
BMM.Assign(BM);
FTColor := BMM.Canvas.Pixels[5,3];
for c := 0 to BMM.Width do
begin
For r := 0 to BMM.height do
begin
if BMM.Canvas.Pixels[c,r] = FTColor then
begin
BMM.Canvas.Pixels[c,r] := clwhite;
BM.Canvas.Pixels[c, r] := clblack;
end
else
BMM.Canvas.Pixels[c,r] := clblack;
end;
end;
if Columns[Index].Alignment = taRightJustify then
ARect.Right := ARect.Right - 15;
end;
end;
if AState and ODS_SELECTED = ODS_SELECTED then
begin
ARect.Left := ARect.Left + 1;
ARect.Top := ARect.Top + 1;
end;
tw := TextWidth(s);
SetBkMode(dc, TRANSPARENT);
if Columns[Index].Alignment = taRightJustify then
begin
DrawText(DC, PChar(s), Length(s), ARect, DT_RIGHT);
Arect.Left := ARect.Right+4;
inc(ARect.Right, 15);
end
else
begin
DrawText(DC, PChar(s), Length(s), ARect, DT_LEFT);
inc(ARect.Left, tw+4);
end;
if fShowsortarrow and (fCurrentsort = Index) then
begin
if ARect.Left + 11 <= ARect.Right then
begin
bitblt(DC, ARect.Left, ARect.Top+5, 11,6, BMM.Canvas.Handle, 0, 0,
cmSRCAND);
bitblt(DC, ARect.Left, ARect.Top+5, 11,6, BM.Canvas.Handle, 0, 0,
cmSrcPaint);
end;
end;
if fXPStyle then
begin
Brush:=CreatePen(PS_SOLID,2,clltGray);
Brush := SelectObject(DC, Brush);
MoveToEx(DC, HoldRect.Left, HoldRect.Bottom-1, nil);
LineTo(DC, HoldRect.Right, HoldRect.Bottom-1);
DeleteObject(Brush);
Brush:=CreatePen(PS_SOLID,1,clltGray);
Brush := SelectObject(DC, Brush);
MoveToEx(DC, HoldRect.Right-1, HoldRect.Bottom-4, nil);
LineTo(DC, HoldRect.Right-1, HoldRect.Top);
DeleteObject(Brush);

end;
finally
b.Free;
p.Free;
BM.Free;
BMM.Free;
end;
end;

procedure TAIStntListview.NewListViewWP(var Msg: TMessage);
var
dis: ^TDrawItemStruct;
hdn: ^THDNotify;
begin
if Msg.Msg = WM_DRAWITEM then
begin
dis := Pointer(Msg.LParam);
DrawHeader(dis.ItemID, dis.rcItem,
dis.ItemState, dis.hDC);
Msg.Result := 1;
end
else if Msg.Msg = WM_NOTIFY then
begin
hdn := Pointer(Msg.LParam);
if hdn.hdr.code = HDN_ENDTRACKW then
begin
Msg.Result := 0;
if fHeaderHandle <> 0 then
InvalidateRect(fHeaderHandle, nil, true);
end;
fOldListViewWP(Msg);
if (hdn.hdr.code = HDN_ITEMCHANGINGW) or (hdn.hdr.code =
HDN_ITEMCHANGINGA) then
begin
if hdn.PItem^.fmt and HDF_OWNERDRAW <> HDF_OWNERDRAW then
begin
hdn.PItem^.fmt := hdn.PItem^.fmt or HDF_OWNERDRAW;
Header_SetItem(fHeaderHandle, hdn.item, hdn.PItem^);
end;
end;
end
else fOldListViewWP(Msg);
if (msg.msg = WM_HSCROLL) and (Items.Count = 0) then
invalidate;
end;


procedure TAIStntListview.RefreshHeader;
begin
if csLoading in componentstate then
else
begin
if fHeaderHandle = 0 then
fHeaderHandle := GetDlgItem(Handle, 0);
if fHeaderHandle <> 0 then
InvalidateRect(fHeaderHandle, nil, true);
end;
end;

procedure TAIStntListview.SetShowSortArrow(const Value: boolean);
begin
fShowSortArrow := Value;
RefreshHeader;
end;

procedure TAIStntListview.SetSortedColumn(const Column: integer;
const Decending: Boolean);
begin
fCurrentsort := Column;
fSortDecending := Decending;
RefreshHeader;
end;

procedure TAIStntListview.SetSortToColumn(const Value: integer);
begin
fSortToColumn := Value;
RefreshHeader;
end;

end.


0 mensajes nuevos