Živě.cz o počítačích a internetu

Tipy a triky v Delphi, díl 108. – Komponenta ListView

Jan Šindelář - 17.9.2003

Komponenta ListView

Vylepšení bude spočívat ve zpřehlednění zobrazení prvků, které ListView obsahuje. Nejčastěji asi používáme ListView k zobrazení seznamu nějakých dat, přičemž tento seznam může mít více sloupců. Ideálním příkladem může být třeba zobrazení seznamu souborů v různých souborových manažerech. Tento styl zobrazení, jak jistě dobře víte, zapneme v Object Inspectoru volbou vsReport u parametru ViewStyle. To také uděláme v našem dnešním příkladu, takže umístěte komponentu ListView na formulář, nastavte zmiňovaný styl a pomocí položky Columns připravte jeden sloupec pro data.

A v čem bude spočívat naše dnešní vylepšení? Ukážeme si, jak jednotlivé řádky, resp. libovolné navazující skupiny řádků, oddělit speciálním řádkem, který bude obsahovat nadpis (například pojmenování prvků v dané skupině) a oddělovací čáru. Vizuálně si tak oddělíme jednotlivé související skupiny prvků dat. Při procházení dat kurzor tento oddělovací řádek přeskočí, takže vše vypadá přesně jak má.

Data do ListView vyplňovat nemusíte, budou vyplněna náhodně. Budeme dále potřebovat knihovnu Commctrl a celou akci spustíme jako tradičně tlačítkem, takže jej přidejte na formulář.

unit Unit1;

interface

uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ComCtrls, StdCtrls, Commctrl, XPMan;

type
TForm1 = class(TForm)
Button1: TButton;
ListView1: TListView;
XPManifest1: TXPManifest;
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;

TLVGROUP = record
cbSize: UINT;
mask: UINT;
pszHeader: LPWSTR;
cchHeader: Integer;
pszFooter: LPWSTR;
cchFooter: Integer;
iGroupIdL: Integer;
stateMask: UINT;
state: UINT;
uAlign: UINT;
end;

tagLVITEMA = packed record
mask: UINT;
iItem: Integer;
iSubItem: Integer;
state: UINT;
stateMask: UINT;
pszText: PAnsiChar;
cchTextMax: Integer;
iImage: Integer;
lParam: lParam;
iIndent: Integer;
iGroupId: Integer;
cColumns: UINT;
puColumns: PUINT;
end;
TLVITEMA = tagLVITEMA;

const
LVM_ENABLEGROUPVIEW = LVM_FIRST + 157;
LVM_MOVEITEMTOGROUP = LVM_FIRST + 154;
LVM_INSERTGROUP = LVM_FIRST + 145;

LVIF_GROUPID = $0100;

LVGF_HEADER = $00000001;
LVGF_ALIGN = $00000008;
LVGF_GROUPID = $00000010;

LVGA_HEADER_LEFT = $00000001;
LVGA_HEADER_CENTER = $00000002;
LVGA_HEADER_RIGHT = $00000004;

var
Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
var
LvGroup: TLVGROUP;
LvItemA: TLVITEMA;
ListItem: TListItem;
I: Byte;
begin
Randomize;
for i := 1 to 10
do
begin
ListItem := ListView1.Items.Add;
ListItem.Caption := IntToStr(Random(100));
end;
SendMessage(ListView1.Handle, LVM_ENABLEGROUPVIEW, 1, 0);

FillChar(LvGroup, SizeOf(TLVGROUP), 0);
with LvGroup
do
begin
cbSize := SizeOf(TLVGROUP);
mask := LVGF_HEADER or LVGF_ALIGN or LVGF_GROUPID;
pszHeader := `Skupina 1`;
cchHeader := Length(LvGroup.pszHeader);
iGroupIdL := 0;
uAlign := LVGA_HEADER_CENTER;
end;
SendMessage(ListView1.Handle, LVM_INSERTGROUP, 0, Longint(@LvGroup));

FillChar(LvGroup, SizeOf(LvGroup), 0);
with LvGroup
do
begin
cbSize := SizeOf(TLVGROUP);
mask := LVGF_HEADER or LVGF_ALIGN or LVGF_GROUPID;
pszHeader := `Skupina 2`;
cchHeader := Length(LvGroup.pszHeader);
iGroupIdL := 1;
uAlign := LVGA_HEADER_RIGHT;
end;
SendMessage(ListView1.Handle, LVM_INSERTGROUP, 1, Longint(@LvGroup));

for I := 0 to ListView1.Items.Count - 1 do
begin
with LvItemA
do
begin
FillChar(LvItemA, SizeOf(TLvItemA), 0);
mask := LVIF_GROUPID;
iItem := I;
iGroupId := Random(2);
end;
SendMessage(ListView1.Handle, LVM_SETITEM, 0, Longint(@LvItemA))
end;
end;

end.

Jak bylo řečeno v úvodu, příklad je funkční pouze pod Windows XP. Ve starších systémech se bude ListView chovat stejně jako obvykle. Je nutné do projektu přidat opět manifestový soubor. V Delphi 7 stačí přidat komponentu XPManifest, ve starších verzích musíte zvolit "ruční" postup (o kterém už byla řeč mnohokrát).

Data budou vložena do ListView náhodně (10 čísel), to je v první části kódu. Následně budou vytvořeny dvě skupiny a v závěru kódu pak budou vložené prvky do těchto skupin (opět náhodně ) rozřazeny. Můžete si také všimnout, že u nadpisů jednotlivých skupin můžete kromě vložení samotného textu také upravit zarovnání apod.