Radek Chalupao programování a počítačích, vývoj software, školení ...
Domů | Články | Ukázky kódu | Tipy a triky | Aktuality | Školení a konzultace | Vývoj software | Freeware | Kontakt

ListBox a ComboBox. Program založený na dialogovém okně.  14.1.2002

V tomto pokračování si ukážeme práci s běžnými ovládacími prvky na dialogu - bude to zejména ListBox a ComboBox. V té souvislosti si také ukážeme, jak můžeme vytvořit projekt založený na dialogovém okně. Založme si nejprve nový projekt, opět prázdnou aplikaci Win32. Do projektu si přidáme zdrojový soubor main.cpp a soubor zdrojů (resource skript) main.rc. Do zdrojů si přidáme dialog s prvky které vidíte na následujícím screen-shotu již hotového programu:

win-api-14

Pokud chceme mít aplikaci založenou pouze na hlavním dialogovém okně, zdrojový kód bude jednodušší než v případě vytváření běžného "overlapped" okna, jako jsme to dělali dosud. Již jsme si řekli v předchozích dílech, pro dilogové okno neregistrujeme vlastní třídu a nebude zde ani smyčka zpráv, protože celá funkce WinMain bude obsahovat vyvolání modálního dialogu funkcí DialogBox:

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInst,
  LPSTR lpCmdLine, int nShow)
{
  return DialogBox(hInstance, MAKEINTRESOURCE(IDD_DIALOG_MAIN),
    NULL, (DLGPROC)DialogProc);
}

Vlastní funkčnost prvků dialogu budeme realizovat v proceduře dialogu, přesněji řečeno pro větší přehlednost budeme volat jednotlivé samostatné funkce, představující handlery zpráv od ovládacích prvků. Procedura okna dialogu je obdobná proceduře "běžného" okna s tím zjednodušením, že nevoláme funkci DefWindowProc pro výchozí zpracování zprávy, ale vrátíme hodnotu FALSE. Pokud zprávu zpracováváme zcela ve vlastní režii, vrátíme hodnotu TRUE. Podívejme se tedy na celou proceduru dialogu a začneme vysvětlováním jednotlivých handlerů:

INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  switch (uMsg)
  {
    case WM_COMMAND:
      switch ( LOWORD(wParam) )
      {
        case IDOK:
        case IDCANCEL:
          EndDialog(hwndDlg, LOWORD(wParam));
          break;
        case IDC_ADD_TEXT:
          OnAddText(hwndDlg, wParam, lParam);
          break;
        case IDC_DELETE_TEXT:
          OnDeleteText(hwndDlg, wParam, lParam);
          break;
      }
      break;
  }
  return FALSE;
}

Budeme chtít na stisknutí tlačítka přidat aktuální obsah edit-boxu do položek list-boxu a dále na druhé tlačítko vybranou položku list-boxu odstranit a její text přidat do combo-boxu nadepsaného "Odebrané položky". Aktuální počet položek list-boxu pak budeme zobrazovat v prvku typu "static".

Veškeré ovládání list-boxu spočívá v posílání příslušných zpráv, popřípadě zjištění návratové hodnoty funkce SendMessage. Uvedu zde přehled těch zpráv, které budeme používat:

LB_ADDSTRING - slouží pro přidání jednoduchého textu do list-boxu. Přidávaný text je v parametyru lParam.

b>LB_GETCOUNT - návratová hodnota zprávy určuje aktuální počet položek list-boxu.

LB_GETCURSEL - vrací index vybrané položky (počítáno od 0) nebo -1, pokud není vybraná žádná položka.

LB_SETCURSEL - nastavuje vybranou položku, její index je v parametru wParam

LB_DELETESTRING - odstraní položku s indexem určeným parametrem wParam.

LB_GETTEXT - naplní nám buffer (parametr lParam) obsahem položky na indexu určeném parametem wParam.

V případě combo-boxu je ovládání obdobné s tím, že zprávy combo-boxu začínají na CB_ místo LB_ jako u list-boxu.

Ještě poznámku k zobrazování číselné hodnoty (zde počet položek list-boxu) v prvku static. V tom případě musíme u vybraného static prvku změnit identifikátor z defaultního IDC_STATIC na nějakou vlastní hodnotu a poté můžeme použít funkci SetDlgItemInt:

BOOL SetDlgItemInt(
  HWND hDlg,       // handle dialogu
  int nIDDlgItem,  // identifikátor prvku
  UINT uValue,     // hodnota požadovaná ke zobrazení
  BOOL bSigned     // určuje zda jde o číslo se znaménkem
);

Takto vybaveni se již můžeme podívat na realizaci přidání položky do list-boxu:

void OnAddText(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
{
  TCHAR chText[150];
  GetDlgItemText(hwndDlg, IDC_EDIT, chText, 150);
  SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_ADDSTRING, 0,
    (LPARAM)chText);
  int count = SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_GETCOUNT, 0, 0);
  SetDlgItemInt(hwndDlg, IDC_LB_COUNT, count, FALSE);
}

Odebrání a přidání odebírané položky do combo-boxu vypadá pak následovně:

void OnDeleteText(HWND hwndDlg, WPARAM wParam, LPARAM lParam)
{
  TCHAR chText[150];
  int curSel = (int)SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_GETCURSEL, 0, 0);
  if ( curSel < 0 ) // není vybraná žádná položka (dostaneme hodnotu -1) return;
  SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_GETTEXT, curSel, (LPARAM)chText);
  SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_ADDSTRING, 0, (LPARAM)chText);
  SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_DELETESTRING, curSel, 0);
  if ( curSel >= SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_GETCOUNT, 0, 0))
    curSel--;
  SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_SETCURSEL, curSel, 0);
  SendDlgItemMessage(hwndDlg, IDC_COMBO, CB_SETCURSEL, 0, 0);
  int count = SendDlgItemMessage(hwndDlg, IDC_LIST_BOX, LB_GETCOUNT, 0, 0);
  SetDlgItemInt(hwndDlg, IDC_LB_COUNT, count, FALSE);
}

Doprovodný projekt je ke stažení zde: win_api_14.zip


Máte připomínku, dotaz nebo komentář k článku a souvisejícími tématy?

Napište a odešlete ji emailem

Copyright © 2019  Radek Chalupa