2006. szeptember 5., kedd
Display a sort order indicator in the column header of a TListView (2)
Problem/Question/Abstract:
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.
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
ComCtrls, StdCtrls, ImgList;
type
TForm1 = class(TForm)
ListView1: TListView;
ImageList1: TImageList;
procedure ListView1ColumnClick(Sender: TObject; Column: TListColumn);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private
{ Private declarations }
FUpArrow, FDownArrow: TBitmap;
procedure SetColumnSortOrder(lv: TListview; Column: TListcolumn);
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
uses
commctrl;
{$R *.DFM}
procedure TForm1.SetColumnSortOrder(lv: TListview; Column: TListcolumn);
var
hdr: HWND;
hdritem: THDItem;
begin
hdr := Listview_GetHeader(lv.handle);
FillChar(hdritem, sizeof(hdritem), 0);
hdritem.Mask := HDI_FORMAT;
Header_GetItem(hdr, column.index, hdritem);
hdritem.Mask := HDI_FORMAT or HDI_BITMAP;
if column.tag = 0 then
hdritem.hbm := FUpArrow.Handle
else
hdritem.hbm := FDownArrow.Handle;
hdritem.fmt := hdritem.fmt or HDF_BITMAP_ON_RIGHT or HDF_BITMAP;
Header_SetItem(hdr, column.index, hdritem);
end;
procedure TForm1.ListView1ColumnClick(Sender: TObject; Column: TListColumn);
begin
Column.Tag := Ord(not Odd(Column.Tag));
SetColumnSortOrder(Sender as TListview, Column);
end;
procedure TForm1.FormCreate(Sender: TObject);
procedure MakeBitmap(var bmp: TBitmap; imageindex: Integer);
begin
bmp := TBitmap.Create;
bmp.Width := imagelist1.width;
bmp.Height := imagelist1.height;
with bmp.Canvas do
begin
Brush.Color := clBtnface;
Brush.Style := bsSolid;
FillRect(Cliprect);
end;
imagelist1.Draw(bmp.canvas, 0, 0, imageindex);
end;
begin
MakeBitmap(FUpArrow, 1);
MakeBitmap(FDownArrow, 0);
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
FUpArrow.Free;
FDownArrow.Free;
end;
end.
Feliratkozás:
Megjegyzések küldése (Atom)
Nincsenek megjegyzések:
Megjegyzés küldése