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

Tipy a triky v Delphi, díl 26. - Barevné položky v Listboxu; Barevné řádky v ListView; Změna barvy ukazatele průběhu; Díra ve formuláři; ProgressBar jako položka v řádku v ListView; Tučné položky v TreeView

Jan Šindelář - 23.1.2002

Barevné položky v Listboxu

Velice jednoduchým způsobem můžeme docílit toho, aby každá položka (řádek) v komponentě Listbox měla jinou barvu. Takto upravený seznam nejenže vypadá lépe, ale působí také daleko přehledněji, než když jsou všechny položky stejné.

Umístěte si na formulář ListBox dvě tlačítka, která nám poslouží pro demonstraci funkčnosti. První tlačítko přidá do ListBoxu položku v červené barvě, druhé tlačítko v zelené. Je též potřeba nastavit u ListBoxu v Object Inspectoru vlastnost ListBox.Style na lbOwnerDrawFixed, což ale u našeho příkladu dělat nemusíte, protože je to nastaveno automaticky v události OnCreate hlavního formuláře.

procedure TForm1.FormCreate(Sender: TObject);
begin
ListBox1.Style := lbOwnerDrawFixed;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer;  Rect: TRect; State: TOwnerDrawState);
begin
with Control as TListBox do
begin
  Canvas.FillRect(Rect);
  Canvas.Font.Color := TColor(Items.Objects[Index]);
  Canvas.TextOut(Rect.Left + 2, Rect.Top, Items[Index]);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
ListBox1.Items.AddObject(`Červený řádek`, Pointer(clRed));
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
ListBox1.Items.AddObject(`Zelený řádek`, Pointer(clGreen));
end;

Barevné řádky v ListView

Velmi podobný příklad jako předchozí je i ten následující. Ukážeme si, jak měnit barevné pozadí jednotlivých řádků u komponenty ListView. Nejprve ji tedy umístíme na formulář, položku ViewStyle v Object Inspectoru nastavíme na vsReport a poté již jen přidáme kód do události OnCustomDrawItem takto:

procedure TForm1.ListView1CustomDrawItem(Sender: TCustomListView;  Item: TListItem; State: TCustomDrawState; var DefaultDraw: Boolean);
begin
with ListView1.Canvas.Brush do
begin
  case Item.Index of
      0: Color := clYellow;
      1: Color := clGreen;
      2: Color := clRed;
  end;
end;
end;

Jak vidíte, kód je velmi jednoduchý. Zde jsou pro ukázku změněny barvy u prvních tří položek.

Změna barvy ukazatele průběhu

Pokud ve svých aplikacích používáte standardní ProgressBar, jistě dobře víte, že jeho barvu nemůžete v Object Inspectoru nastavit, a ta tedy zůstává nastavená dle systému (obvykle modře). Existuje ale celkem jednoduchý způsob, jak mu svou barvu "vnutit". V následující ukázce se nastaví barva ProgressBaru na zelenou. K celé "akci" budeme potřebovat knihovnu Commctrl (pozor, neplést s knihovnou ComCtrls).

...
uses commctrl;
...

procedure TForm1.Button1Click(Sender: TObject);
begin
SendMessage(ProgressBar1.Handle, PBM_SETBARCOLOR, 0, clGreen);
end;

Díra ve formuláři

Následující příklad patří ke klasickým a oblíbeným tipům na různých diskusních fórech. Osobně mě moc nenapadá na vyloženě praktické využití, ale ne všechno musí mít nějaký konkrétní účel. Díra ve formuláři může někdy působit zajímavě, takže si tento tip můžete přidat k dalším grafickým hračkám, které jsme si už v seriálu ukazovali. Pro ty, kteří naprosto netuší, o čem je zde řeč, snad jen krátké vysvětlení. Díra ve formuláři je prostě díra, neboli místo na formuláři, které je průhledné, a proto je vidět to, co je pod formulářem (pracovní plocha, okna jiných aplikací apod.).

Tvar a umístění díry si můžete vymyslet dle vlastního uvážení. V naší ukázce je to kruhová díra v levém horním rohu formuláře, která se objeví po kliknutí na příslušné tlačítko:

procedure TForm1.Button1Click(Sender: TObject);
var
  region1, region2: hrgn;
begin
region1 := CreateRectRgn(0, 0, Width, Height);
region2 := CreateEllipticRgn(30, 30, 200, 200);
CombineRgn(region1, region1, region2, RGN_DIFF);
SetWindowRgn(Handle, region1, True);
end;

ProgressBar jako položka v řádku v ListView

Následující tip je hádám hodně užitečný a doufám, že jej řada z vás použije. Možná, že jste kdysi byli aktivními uživateli programu Napster. Proč o něm mluvím? Jistě si vzpomínáte, že v seznamu právě stahovaných písniček byl v jednom ze sloupců také ukazatel průběhu stahování (ProgressBar) té které písničky. A to se právě teď naučíme. Vložíme si do ListView sloupec, kde jednotlivými položkami budou právě takovéto ukazatele průběhu. Použití tohoto triku je velmi užitečné v těch případech, kdy vaše aplikace vykonává paralelně několik činností a vy chcete uživateli ukázat jejich seznam (činností) a současně poskytnout informaci o tom, kolik které akci zbývá do ukončení (například právě ono stahování souborů z Internetu apod.).

Pro naši ukázku si na formulář umístěte jeden ListView (není třeba u něj žádné vlastnosti nastavovat, o vše se postará program sám) a dvě tlačítka. První tlačítko způsobí zobrazení jednotlivých položek a stylu zobrazení ListView (vlastně taková příprava před samotnou akcí) a druhé tlačítko je vlastně simulace nějaké činnosti, po jehož kliknutí se zvětší hodnota ProgressBaru, aby byla vidět funkčnost celé ukázky.

procedure TForm1.Button1Click(Sender: TObject);
var
r: TRect;
pb: TProgressBar;
begin
Listview1.Columns.Add.Width := 100;
Listview1.Columns.Add.Width := 200;
Listview1.ViewStyle := vsReport;
Listview1.Items.Add.Caption := `Text`;
r := Listview1.items[0].DisplayRect(drBounds);
r.left := r.Left + Listview1.columns[0].Width;
r.right := r.Left + Listview1.columns[1].Width;
pb:= TProgressBar.Create(self);
pb.Parent := Listview1;
pb.BoundsRect := r;
pb.Position := 30;
Listview1.items[0].Data := pb;
end;

procedure TForm1.Button2Click(Sender: TObject);
var
pb: TProgressBar;
begin
pb := TProgressBar(Listview1.Items[0].Data);
pb.StepIt;
end;

Tučné položky v TreeView

Na závěr tu máme ještě jedno vizuální vylepšení, tentokrát pro TreeView. Naučíme se, jak požadované položky zobrazit tučně, a tím je zvýraznit. Takto můžete zvýraznit například všechny kořenové prvky pro zpřehlednění, ale použitelnost je pochopitelně univerzální, protože jediným parametrem funkce je index prvku, který chcete změnit, a zda jej chcete tučně či ne.

Umístěte si tedy na formulář TreeView, naplňte jej cvičnými daty a vzhůru do experimentování. V naší ukázce si změníme hned první položku (s indexem 0). Opět je použita knihovna CommCtrl.

procedure SetNodeBoldState(Node: TTreeNode; Value: Boolean);
var
  TVItem: TTVItem;

begin
if not Assigned(Node) then Exit;
with TVItem do
begin
  mask := TVIF_STATE or TVIF_HANDLE;
  hItem := Node.ItemId;
  stateMask := TVIS_BOLD;
  if Value then state := TVIS_BOLD
                else state := 0;
  TreeView_SetItem(Node.Handle, TVItem);
end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
SetNodeBoldState(TreeView1.Items[0],True);
end;

A to je pro dnešek všechno. Příště u dnešního tématu ještě vydržíme a i nadále si budeme pohrávat se standardními komponentami a vylepšovat je.