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

Tipy a triky v Delphi, díl 148. - radiobuttony v listboxu

Jan Šindelář 21.7.2004

Prázdniny a dovolené jsou v plném proudu, takže dnes to bude něco méně náročného. Opět to bude vylepšování existujících komponent a tentokrát si položky v ListBoxu zobrazíme jako prvky RadioButtonu.

Bude to opravdu jednoduchý tip pro drobné vylepšení vzhledu ListBoxu. Funkčnost se nijak nezmění, tedy ani nezlepší. Pokud nám slouží ListBox výhradně pro výběr vždy jen jedné konkrétní položky z mnoha, můžeme přidat k jednotlivým řádkům "kolečko" z RadioButtonu. Tím ještě v uživateli umocníme představu o tom, že z ListBoxu má (resp. lze) vybrat opravdu jen jednu položku. Nezapomeňte tedy volbu Multiselect nastavit na False.

Postup je snadný. Umístěte na formulář ListBox a naplňte několika řádky dat. Dále musíme nejprve nastavit styl vykreslování ListBoxu na OwnerDraw, čím na sebe bereme veškerou zodpovědnost za jeho vzhled. V našem případě je to uděláno programově v události OnCreate a je zde nastavena i velikost řádku na 20 bodů. V události OnDrawItem pak kreslíme samotné prvky, kdy nakreslíme "rámeček", RadioButton a vypíšeme pak samotný text.

unit Unit1;

interface

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

type
  TForm1 = class(TForm)
    ListBox1: TListBox;
    procedure FormCreate(Sender: TObject);
    procedure ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
    procedure ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  ListBox1.Style := lbOwnerDrawVariable;
  ListBox1.ItemHeight := 20;
end;

procedure TForm1.ListBox1DrawItem(Control: TWinControl; Index: Integer; Rect: TRect; State: TOwnerDrawState);
var
  drawRect: TRect;
begin
  with ListBox1.Canvas do
  begin
    FillRect(rect);
    drawRect.Left := rect.Left + 1;
    drawRect.Right := Rect.Left + 13;
    drawRect.Bottom := Rect.Bottom;
    drawRect.Top := Rect.Top;
    if odSelected in State then DrawFrameControl(Handle, drawRect, DFC_BUTTON, DFCS_BUTTONRADIO or DFCS_CHECKED)
    else DrawFrameControl(Handle, drawRect, DFC_BUTTON, DFCS_BUTTONRADIO);
    TextOut(15, rect.Top + 3, ListBox1.Items[Index]);
  end;
end;

procedure TForm1.ListBox1MouseMove(Sender: TObject; Shift: TShiftState; X, Y: Integer);
begin
//  ListBox1.ItemIndex := ListBox1.ItemAtPos(Point(x, y), True);
end;

end.

Pokud budete chtít ListBox opravdu "přeplácat", můžete přidat i automatické označení položek po najetí myší (příslušný řádek je označen v kódu jako poznámka) v události OnMouseMove, jak jsme si ukazovali nedávno. To už by bylo na uživatele ale asi příliš, proto to nechám na vaší úvaze.