Ovládací prvek ListBox (MFC a C++)

Seznamy se nejčastěji používají k zobrazení přehledu informací. Umožňují, aby si uživatel mohl vybrat jednu (nebo více) z nabízených možností. Dokáží také převinovat svůj obsah, takže do nich můžeme umístit více položek, než je fyzická velikost seznamu.

Takhle vypadá ListBox

Seznamy zastupuje třída CListBox založená na struktuře WNDCLASS typu "STATIC" a zobrazují textové řetězce ve svislém sloupci. Položka, která je aktuálně vybraná, je zvýrazněna barvou COLOR_HIGHLIGHT.

Vytvoření seznamu

Uvedu rovnou zdrojový kód, popíši jej potom:

CListBox m_listbox;
m_listbox.Create(WS_VISIBLE | WS_CHILD | LBS_STANDARD,CRect(10,10,100,300),
  this,IDC_LISTBOX1);

Zde je význam jednotlivých parametrů:

1. Styl seznamu
2. Obdélník, který vymezuje plochu seznamu
3. Rodič seznamu
4. Identifikační číslo (ID) seznamu

Pro nás nejzajímavější bude asi první parametr, který určuje styl seznamu. Pomocí něj totiž můžeme navolit vlastnosti seznamu (LBS_něco). Uvedu zde některé z nich, zbytek si můžete vyhledat v dokumentaci.

  • LBS_SORT - položky budou řazeny podle abecedy
  • LBS_NOSEL - položky seznamu se budou moci pouze prohlížet, nikoli vybírat
  • LBS_NOTIFY - seznam bude odesílat zprávy svému vlastníku
  • LBS_MULTIPLESEL - vytvoří seznam s vícenásobných výběrem
  • LBS_STANDARD - je to kombinace stylů WS_BORDER, WS_SCROLL, LBS_NOTIFY a LBS_SORT

Přidání a odebrání položek

Pokud budete chtít do seznamu přidat nějaké položky, můžete použít jednu z funkcí AddString a InsertString . Je důležité si uvědomit, že funkce AddString přidá položku na konec seznamu, ovšem funkce InsertString přidá položku na místo, které je určené prvním parametrem. Pokud je nastaveno LBS_SORT přidá se položka podle abecedy.

Funkce AddString přijímá ve svém parametru objekt třídy CString, ve kterém je uložen text nové položky.

CString text="Moje položka";
m_listbox.AddString(text);   //přidání položky

Funkce InsertString zase přijímá ve svém prvním parametru umístění položky a v druhém text položky. Následující příkaz tedy umístí položku na třetí místo.

m_listbox.InsertString(2,text); //umístí text jako třetí položku

Jestliže chcete položku odebrat, použijte funkci DeleteString , které předáte index položky k vymazání. Pro vymazání celého seznamu můžete využít funkci ResetContent , která nevyžaduje žádné argumenty. A nakonec k zjištění počtu položek v seznamu slouží funkce GetCount .

Vyhledávání a výběr položek

Třída CListBox obsahuje také funkce, pomocí kterých můžete zjistit, která z položek je vybraná nebo vybrat položku z programu. Ke zjištění výběru slouží funkce GetCurSel , která vrací index vybrané položky. Pro nastavení výběru slouží funkce SetCurSel , které předáte index položky, která se má vybrat. Také by se vám mohla hodit funkce SelectString , která vybere položku podle textu, který jí předáte (první parametr je index položky od které se bude vyhledávat, -1 znamená od začátku).

Vybere položku, která začíná textem "Mapa":

m_listbox.SelectString(-1,"Mapa");   //vybere položku

Jestliže chcete vyhledávat v seznamu tak, aby se nezměnil výběr, můžete použít např. funkci FindString , které předáte text k vyhledání a ona vám vrátí index položky, která text obsahuje. Pokud žádná taková neexistuje vrátí LB_ERR. Index si potom můžete převést na text pomocí funkce GetText . Příklad vše objasní:

CString text;

int index=m_listbox.FindString(-1,"Hledaná položka");
m_listbox.GetText(index,text);

Pokud má seznam nastaven příznak LBS_MULTIPLESEL (vícenásobný výběr), nemůžeme používat funkce SetCurSel, GetCurSel ani SelectString. Místo nich musíme použít SetSel a SelItemRange . Příklad zde uvedený vybere položky 0,1,2,3,5,7 a 8 a zruší výběr u položky 4.

m_listbox.SelItemRange(TRUE,0,3);
m_listbox.SetSel(5,TRUE);
m_listbox.SelItemRange(TRUE,7,8);
m_listbox.SetSel(4,FALSE);

Poslední funkcí, kterou zde uvedu, bude GetSelCount , která vrací počet vybraných položek.

Zprávy zasílané seznamem

Když má seznam nastaven příznak LBS_NOTIFY, tak odesílá nadřazenému oknu zprávy o změnách v seznamu prostřednictvím zpráv WM_COMMAND. Mfc toto ovšem zjednodušuje tím, že zprávu namapuje makrem ON_LBN, které se umístí do mapy zpráv. Nyní výpis jednotlivých zpráv:

ON_LBN_SETFOCUS - při zaměření seznamu
ON_LBN_KILLFOCUS - když seznam ztratí zaměření
ON_LBN_SELCHANGE - při změně výběru
ON_LBN_DBLCLK - při poklepání na položku
ON_LBN_CANCEL - při zrušení výběru

Nejčastěji budete používat asi makro ON_LBN_SELCHANGE, které je odesláno při změně výberu. Příklad, který nyní uvedu, vždy po změně výběru zobrazí zprávu s textem vybrané položky.

//v mapě zpráv
ON_LBN_SELCHANGE(IDC_LISTBOX1,OnListChange)

...

void COkno::OnListChange()
{
  CString text;
  int index=m_listbox.GetCurSel();
  m_listbox.GetText(index,text);
  MessageBox(text);
}

Vzhled seznamu

Určitě jste si všimli, že když seznam vytvoříte tak, jak jsem to psal na začátku tohoto článku, má takové ploché okraje, což v systému Windows XP nevypadá dobře. Pokud to chceme napravit, musíme k rozšířenému stylu přidat WS_EX_CLIENTEDGE . To můžeme udělat dvěma způsoby, buď pomocí funkce CreateEx nebo si vytvořit novou třídu zděděnou od CListBox a ve funkci PreCreateWindow přidat styl. Uvedu zde obě metody.

Ta první:

m_listbox.CreateEx(WS_EX_CLIENTEDGE,"LISTBOX",NULL,WS_VISIBLE | WS_CHILD |
  LBS_STANDARD,CRect(10,10,150,200),this,IDC_LISTBOX1);

A druhá:

BOOL C3DListBox::PreCreateWindow(CREATESTRUCT& cs)
{
  if(!CListBox::PreCreateWindow(cs))
    return FALSE;
    
  cs.dwExStyle|=WS_EX_CLIENTEDGE;
  
  return TRUE;
}

UPOZORNĚNÍ: Jedná se o archiv článků z let 2003 - 2005, uvedené technologie či postupy již mohou být neaktuální.