Používáním tohoto webu souhlasíte s použitím souborů cookie. Kliknutím zavřít.
Pracujeme s ComboBoxem.
2.2.2002
V tomto článku poznáme trochu blíže ovládací prvek
ComboBox, česky překládaný jako
rozbalovací seznam. Podobně jako ListBox umožňuje uživateli výběr z existujících položek. Navíc umožňuje také uživateli přímo zapisovat text do editačního pole, pokud má nastaven příslušný styl.

Řekneme si nejdříve o 3 typech ComboBoxu:
Simple ComboBox
Simple ComboBox má ve stylu okna hodnotu
CBS_SIMPLE, kterou uvedeme při jeho ručním vytváření nebo ve skriptu prostředků. V editoru prostředků pak jednoduše nastavíme vlastnost
Type na hodnotu
Simple. Tento typ ComboBoxu má oba prvky (Edit i ListBox) trvale zobrazené. Při změně výběru v ListBoxu se text vybraného řádku automaticky zobrazí v editačním poli ComboBoxu. Uživatel může do editačního pole také zapisovat vlastní text. Pozor! V editoru prostředků musíme po nastavení typu na Simple roztáhnout ComboBox do příslušné požadované výšky. V opačném případě by se zobrazoval pouze ve formě jednoho řádku, ve které by sice bylo možné klávesami šipka nahoru nebo dolů listovat, ale nedosáhli bychom výsledku, který jsme pravděpodobně zamýšleli.
Drop down
Tento typ ComboBoxu (ve stylu okna má hodnotu
CBS_DROPDOWN) je představován editačním polem (prvek Edit) s rozbalovacím tlačítkem, přičemž rozbalovací část (prvek ListBox) může být rozbalena pouze v době kdy má ComboBox fokus. Jakmile uživatel přeskočí (například klávesou
Tab) na jiné okno, ComboBox se automaticky zabalí, aniž by uživatel proti tomu mohl cokoli dělat. Také v tomto typu ComboBoxu je uživateli umožněno zapisovat do editačního pole. Pozor! Častým problémem začátečníků bývá nastavení dostatečné výšky rozbalovacího seznamu. Pokud totiž necháte ComboBox tak, jak jej umístíte na dialog v editoru prostředků bude i při větším počtu položek "rozbalen" pouze jeden řádek vzhledu prvku Edit s malými skrolovacími šipkami, kterými je možné procházet položky ComboBoxu. Správné nastavení provedeme v editoru prostředků kliknutím na rozbalovací šipku, po kterém se nám zobrazí roztahovací obdélník, který pak můžeme tažením za jeho spodní okraj roztáhnout do velikosti, která představuje maximální výšku, do které se rozbalí ComboBox za běhu programu.
Drop List
Tento typ ComboBoxu (styl okna
CBS_DROPDOWNLIST) je podobný předchozímu s tím rozdílem, že uživatel nemůže zapisovat vlastní text. Jeho nastavení v editoru prostředků je stejné jako u předchozího typu
Drop down.
Naplnění položek ComboBoxu
Položky ComboBoxu můžeme programově přidávat jednou ze dvou zpráv
CB_ADDSTRINGa
CB_INSERTSTRING. Zpráva
CB_ADDSTRING přidá položku na konec a v případě, že má ComboBox nastavenu vlastnost
CBS_SORT, je položka automaticky zatříděna podle abecedy. Vlastnost (styl okna)
CBS_SORT nastavíme v editoru prostředků jako vlastnost
Sort, která má ve Visual C++ výchozí hodnotu
true, i když osobně si myslím, že v praxi u většiny ComboBoxů, které jsem použil, jsem toto automatické třídění zrušil. Druhou zprávou pro přidání položky ComboBoxu je
CB_INSERTSTRING, jejímž parametrem
lParam je text přidávané položky a parametr
wParam určuje index, který má nově přidaná položka mít. Na rozdíl od zprávy
CB_ADDSTRING namá nastavení stylu
CBS_SORT (automatické třídění) žádný vliv a položka je přidána tam, kam řekneme. Pokud chceme touto zprávou přidat položku na konec, uvedeme jako parametr wParam hodnotu -1. Ukázku přidání položek ComboBoxu funkci voláme při zachycení zprávy
WM_INITDIALOG vidíte v následujícím výpisu:
void NaInitDialog(HWND hWnd)
{
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)_T("1. řádek"));
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)_T("2. řádek"));
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)_T("3. řádek"));
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_ADDSTRING, 0, (LPARAM)_T("4. řádek"));
// přidání dalších položek ...
}
Detekce změny výběru, zjištění a nastavení výběru v programu
V následujícím kódu si ukážeme jak detekovat změnu výběru položky ComboBoxu. Budeme zachytávat změnu jednoho z rozbalovacích ComboBoxů, zjistíme index aktuálně vybrané položky a stejnou položku (index) nastavíme jako vybranou ComboBoxu typu
Simple. Funkce kterou budeme volat při zjištění změny výběru uživatelem, vypadá takto:
void NaZmenaVyberu(HWND hCombo)
{
LRESULT vyber = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
SendDlgItemMessage(GetParent(hCombo), IDC_SIMPLE, CB_SETCURSEL, vyber, 0);
}
Jak a kdy volat tuto zprávu? Při změně výběru dostane vlastník ComboBoxu, tedy naše dialogové okno oznamovací zprávu
CBN_SELCHANGE, která přijde prostřednictvím zprávy
WM_COMMAND. V následujícím výseku z kódu procedury dialogu je vidět její obsluha:
INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch ( uMsg )
{
case WM_COMMAND:
switch ( LOWORD(wParam) )
{
case IDC_DROPDOWN:
case IDC_DROPLIST:
if ( HIWORD(wParam) == CBN_SELCHANGE)
NaZmenaVyberu((HWND)lParam);
break;
case IDC_SIMPLE:
ZjistiTextPolozky((HWND)lParam);
break;
// další příkazy ...
}
break;
// Další zprávy ...
}
return FALSE;
}
Využíváme parametru
lParam, který u zprávy
WM_COMMAND představuje handle okna ovládacího prvku, kterého se zpráva týká. Jak je vidět z dosavadního výkladu, práce s položkami ComboBoxu je obdobná práci s ListBoxem, který jsme již poznali. Rozdílem je pouze první písmeno v názvech identifikátorů příslušných zpráv. Ukažme si ještě spíše pro připomenutí, jak načíst text aktuálně vybrané položky ComboBoxu. Budeme tentokrát detekovat změnu ComboBoxu typu
Simple a vypisovat do prvku Static její text. Při detekci změny výběru budeme vola následující funkci, jejíž volání také vidíte ve výpisu nad sebou:
void ZjistiTextPolozky(HWND hCombo)
{
LPTSTR lpText;
LRESULT vyber = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
LRESULT delkaTextu = SendMessage(hCombo, CB_GETLBTEXTLEN, vyber, 0);
lpText = (LPTSTR)HeapAlloc(GetProcessHeap(), 0,
(delkaTextu+1) * sizeof(TCHAR));
SendMessage(hCombo, CB_GETLBTEXT, vyber, (LPARAM)lpText);
SetDlgItemText(GetParent(hCombo), IDC_COMBO_TEXT, lpText);
HeapFree(GetProcessHeap(), 0, lpText);
}
Na závěr si ještě ukážeme jak lze programově rozbalit položky ComboBoxu. Na dialog si přidáme tlačítko a v obsluze jeho stisknutí (to jistě již pravidelný čtenář zná) zavoláme tuto funkci, která rozbalí jeden z ComboBoxů na dialogu a navíc nastaví výběr na 5. položku:
void NaRozbalit(HWND hWnd)
{
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_SHOWDROPDOWN, (WPARAM)TRUE, 0);
SendDlgItemMessage(hWnd, IDC_DROPDOWN, CB_SETCURSEL, (WPARAM)4, 0);
}
Doprovodný projekt je ke stažení zde:
win_api_combobox.zip