29.1.2002
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); }Doprovodný projekt je ke stažení zde: win_api_uk_listbox.zip
Školení
Kontakt
739 219 991
live:radekchalupa_1
Nové články