Učíme se Win API - uživatelsky kreslený ListBox - Builder.cz - Informacni server o programovani

Odběr fotomagazínu

Fotografický magazín "iZIN IDIF" každý týden ve Vašem e-mailu.
Co nového ve světě fotografie!

 

Zadejte Vaši e-mailovou adresu:

Kamarád fotí rád?

Přihlas ho k odběru fotomagazínu!

 

Zadejte e-mailovou adresu kamaráda:



C/C++

Učíme se Win API - uživatelsky kreslený ListBox

winapi_logo

21. listopadu 2002, 00.00 | V tomto pokračování si ukážeme další uživatelsky kreslený prvek. Bude jím ListBox, jehož položkami budou vybrané soubory. U každé položky bude zobrazovat ikonu asociovanou s daným souborem a dále jméno souboru s možností víceřádkového textu.

Uživatelsky kreslený ListBox

V tomto pokračování ještě zůstaneme u uživatelsky kreslených prvků. Vytvoříme si ListBox, do kterého budeme jako položky přidávat vybrané soubory. V ListBoxu bude pak zobrazena ikona asociovaná s příslušným souborem a jméno souboru vypsané tak, že v případě delšího názvu bude povolen víceřádkový výpis do zbylého prostoru položky ListBoxu, jak vidíte na obrázku:

U uživatelsky kresleného ListBoxu (a podobně některých další ovládacích prvků) musíme kromě zprávy WM_DRAWITEM reagovat na zprávu WM_MEASUREITEM, ve které systému řekneme požadované rozměry (v případě ListBoxu výšku) položky. V našem případě budeme zobrazovat velké ikony, takže výšku položky nastavíme a výšku ikony plus řekněme 4 pixely. Tuto zprávu ošetříme přímo v proceduře dialogu, pro obsluhu zprávy WM_DRAWITEM si vytvoříme vlastní funkci, stejně jako pro zobrazení dialogu výběru souboru a přidání vybraného souboru jako položky ListBoxu. Procedura dialogu bude vypadat následovně:

/////////////////////////////////////////////////////////////////////////////
// Procedura dialogu

INT_PTR CALLBACK DialogProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
  LPMEASUREITEMSTRUCT lpMIS;
  switch ( uMsg )
  {
    case WM_COMMAND:
      switch ( LOWORD(wParam) )
      {
        case IDOK:
          EndDialog(hWnd, IDOK);
          break;
        case IDCANCEL:
          EndDialog(hWnd, IDCANCEL);
          break;
        case IDC_PRIDAT:
          PridatSoubor(hWnd);
          break;
      }
      break;
    case WM_INITDIALOG:
      break;
    case WM_DRAWITEM:
      DrawItem((LPDRAWITEMSTRUCT)lParam);
      break;
    case WM_MEASUREITEM:
      lpMIS = (LPMEASUREITEMSTRUCT)lParam;
      lpMIS->itemHeight = GetSystemMetrics(SM_CYICON) + 4;
      break;
  }
  return FALSE;
}

Funkce pro přidání vybraného souboru jako položky je již pro čtenáře seriálu jednoduchá, pro úplnost ji zde uvedu:

void PridatSoubor(HWND hWnd)
{
  TCHAR szSoubor[MAX_PATH];
  lstrcpy(szSoubor, _T(""));
  OPENFILENAME ofn;
  ZeroMemory(&ofn, sizeof(OPENFILENAME));
  ofn.lStructSize = sizeof(OPENFILENAME);
  ofn.hwndOwner = hWnd;
  ofn.lpstrFile = szSoubor;
  ofn.nMaxFile = sizeof(szSoubor);
  ofn.lpstrFilter = TEXT("Všechny soubory\0*.*\0");
  ofn.lpstrFileTitle = NULL;
  ofn.nMaxFileTitle = 0;
  ofn.lpstrInitialDir = NULL;
  ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST;
  if ( !GetOpenFileName(&ofn) ) 
    return;
  SendDlgItemMessage(hWnd, IDC_LISTBOX, LB_ADDSTRING, 0,
    (LPARAM)szSoubor);
}

Nyní zbývá to nejdůležitější, vykreslit položku ListBoxu při obdržení zprávy WM_DRAWITEM. Identifikátor dané položky dostaneme jako prvek itemID struktury DRAWITELSTRUCT. Z toho je již snadné získat text položky, což je plné jméno souboru. Handle asociované ikony získáme pomocí funkce ExtractAssociatedIcon. Dále zjistíme, zda se jedná o právě vybranou položku otestování přítomnosti hodnoty ODS_SELECTED v prvku itemState. Podle výsledku vyplníme plochu položky jedním z příslušných systémových štětců. Poté vykreslíme ikonu do levé části položky a do zbylého obdélníka vypíšeme název souboru funkcí DrawText, která umožňuje nastavit automatické zalamování řádek v rámci daného obdélníka.

void DrawItem(LPDRAWITEMSTRUCT lpDIS)
{
  TCHAR szSoubor[MAX_PATH];
  HBRUSH hbPozadi;
  SendMessage(lpDIS->hwndItem, LB_GETTEXT, lpDIS->itemID, (LPARAM)szSoubor);
    WORD index = 0;
  HICON hIcon = ExtractAssociatedIcon(g_hInstance, szSoubor, &index);
  if ( lpDIS->itemState & ODS_SELECTED )
  {
    hbPozadi = GetSysColorBrush(COLOR_HIGHLIGHT);
    SetTextColor(lpDIS->hDC, GetSysColor(COLOR_HIGHLIGHTTEXT));
  }
  else
  {
    hbPozadi = GetSysColorBrush(COLOR_WINDOW);
    SetTextColor(lpDIS->hDC, GetSysColor(COLOR_WINDOWTEXT));
  }
  
  SetBkMode(lpDIS->hDC, TRANSPARENT);
  FillRect(lpDIS->hDC, &lpDIS->rcItem, hbPozadi);
  
  DrawIcon(lpDIS->hDC, lpDIS->rcItem.left + 1,
    lpDIS->rcItem.top + 2, hIcon);
  RECT rect;
  CopyMemory(&rect, &lpDIS->rcItem, sizeof(RECT));
  rect.left += 34;
  DrawText(lpDIS->hDC, szSoubor, -1, &rect,
    DT_WORDBREAK | DT_VCENTER);
}

Zde si můžete stáhnout doprovodný projekt: uk_listbox.zip


Obsah seriálu (více o seriálu):

Tématické zařazení:

 » Rubriky  » C/C++  

 

 

 

Nejčtenější články
Nejlépe hodnocené články

 

Přihlášení k mému účtu

Uživatelské jméno:

Heslo: