Author: Tomas Rutkauskas
Does anyone know how to add custom painting to the column headings in vsReport mode
(short of ownerdrawing everything)? I'd like to add indication of sort order and
more. I don't think the columns ImageIndex is a satisfactory solution. I would like
the image of the sort indicator on the right.
Answer:
The problem is that not all versions of the listview common control support this.
You have to drop to the API to make use of it. This is somewhat ackward (the common
controls seem to get more cumbersome to use with each version). The listviews
header line is an actual header control. A header control can display either images
from an imagelist or a bitmap. Only the bitmap can be arranged to the right of the
caption text. The listview offers no direct method to set a bitmap for a header, so
you have to get the header controls handle and send messages to it directly. The
bitmap you use should be created on form creation and destroyed on form destruction.
The following example shows the principle. There is a major snag here, though.
Since the VCL listview has no idea that you changed some header properties it will
happily wipe out what you did every time it feels like resetting some of the header
properties, e.g. when the user resizes one of the columns. This can be dealt with
if needs be, by subclassing the header control to trap the HDM_SETITEM messages
that change the item properties. The TListview class already subclasses the header
but the method used is private and not virtual, so not accessible.
1 unit Unit1;
2
3 interface
4
5 uses
6 Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
7 ComCtrls, StdCtrls, ImgList;
8
9 type
10 TForm1 = class(TForm)
11 ListView1: TListView;
12 ImageList1: TImageList;
13 procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
14 procedure FormCreate(Sender: TObject);
15 procedure FormDestroy(Sender: TObject);
16 private
17 { Private declarations }
18 FUpArrow, FDownArrow: TBitmap;
19 procedure SetColumnSortOrder(lv: TListview; Column: TListcolumn);
20 public
21 { Public declarations }
22 end;
23
24 var
25 Form1: TForm1;
26
27 implementation
28
29 uses
30 commctrl;
31
32 {$R *.DFM}
33
34 procedure TForm1.SetColumnSortOrder(lv: TListview; Column: TListcolumn);
35 var
36 hdr: HWND;
37 hdritem: THDItem;
38 begin
39 hdr := Listview_GetHeader(lv.handle);
40 FillChar(hdritem, sizeof(hdritem), 0);
41 hdritem.Mask := HDI_FORMAT;
42 Header_GetItem(hdr, column.index, hdritem);
43 hdritem.Mask := HDI_FORMAT or HDI_BITMAP;
44 if column.tag = 0 then
45 hdritem.hbm := FUpArrow.Handle
46 else
47 hdritem.hbm := FDownArrow.Handle;
48 hdritem.fmt := hdritem.fmt or HDF_BITMAP_ON_RIGHT or HDF_BITMAP;
49 Header_SetItem(hdr, column.index, hdritem);
50 end;
51
52 procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
53 begin
54 Column.Tag := Ord(not Odd(Column.Tag));
55 SetColumnSortOrder(Sender as TListview, Column);
56 end;
57
58 procedure TForm1.FormCreate(Sender: TObject);
59
60 procedure MakeBitmap(var bmp: TBitmap; imageindex: Integer);
61 begin
62 bmp := TBitmap.Create;
63 bmp.Width := imagelist1.width;
64 bmp.Height := imagelist1.height;
65 with bmp.Canvas do
66 begin
67 Brush.Color := clBtnface;
68 Brush.Style := bsSolid;
69 FillRect(Cliprect);
70 end;
71 imagelist1.Draw(bmp.canvas, 0, 0, imageindex);
72 end;
73
74 begin
75 MakeBitmap(FUpArrow, 1);
76 MakeBitmap(FDownArrow, 0);
77 end;
78
79 procedure TForm1.FormDestroy(Sender: TObject);
80 begin
81 FUpArrow.Free;
82 FDownArrow.Free;
83 end;
84
85 end.
|