Využijte možnosti školení a konzultací distanční formou s využitím online komunikace (Skype a další)
// Při spuštění nastavíme tlačítku bitmapu (handler WM_INITDIALOG) void On_InitDialog(HWND hWnd) { SendDlgItemMessage(hWnd, IDC_HONZA, BM_SETIMAGE, (WPARAM)IMAGE_BITMAP, (LPARAM)LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_HONZA))); }Tato funkce je volána v handleru zprávy WM_INITDIALOG, tedy "těsně" před prvním zobrazením dialogu na obrazovce. Ještě musíme v editoru zdrojů příslušnému tlačítku nastavit vlastnost "Bitmap" na True (styl okna BS_BITMAP). Nyní se podívejme na další 2 tlačítka, která jsou již plně uživatelsky kreslena. V editoru zdrojů musíme takovým tlačítkům nastavit vlastnost "Owner Draw" na True (odpovídá to stylu okna BS_OWNERDRAW). Když nyní dialog spustíme, tyto tlačítka vůbec na dialogu nebudou vidět, musíme je tedy ve správný čas kreslit sami. O tom, kdy nastal ten správný čas, nás informuje systém. Rodičovskému oknu, tedy našemu dialogu je poslána zpráva WM_DRAWITEM, obsahující v parametru lParam adresu struktury DRAWITEMSTRUCT:
typedef struct tagDRAWITEMSTRUCT { UINT CtlType; UINT CtlID; UINT itemID; UINT itemAction; UINT itemState; HWND hwndItem; HDC hDC; RECT rcItem; ULONG_PTR itemData; } DRAWITEMSTRUCT;V této struktuře máme všechny potřebné informace k vykreslení buttonu (totéž platí i o dalších prvcích podporující uživatelské kteslení - listbox, combobox apod.). Struktura obsahuje také informace o stavu tlačítka - zda je například právě zamáčknuté, zda má klávesnicový fokus apod. Podívejme se nyní na konkrétní realizaci. V projektu máme 2 tlačítka kreslená uživatelsky. Chceme mít na obou stejné pozadí tvořené bitmapou. Tuto bitmapu si tedy přidáme do zdrojů (IDB_POZADI). Zobrazované ikony jsou systémové ikony (IDI_INFORAMTION a IDI_ERROR) a každé tlačítko má svůj vlastní text. Vše ostatní již realizujeme v handleru zprávy WM_DRAWITEM, ve kterém zavoláme následující vlastní kreslící funkci, které jako parametr předáme lParam procedury dialogu.
// Uživatelské kreslení tlačítek void On_DrawItem(LPDRAWITEMSTRUCT lpDIS) { HBRUSH hbPozadi = CreatePatternBrush(LoadBitmap(g_hInst, MAKEINTRESOURCE(IDB_POZADI))); if ( lpDIS->itemState & ODS_SELECTED ) DrawFrameControl(lpDIS->hDC, &lpDIS->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH | DFCS_PUSHED); else DrawFrameControl(lpDIS->hDC, &lpDIS->rcItem, DFC_BUTTON, DFCS_BUTTONPUSH); InflateRect(&lpDIS->rcItem, -4,-4); FillRect(lpDIS->hDC, &lpDIS->rcItem, hbPozadi); SetBkMode(lpDIS->hDC, TRANSPARENT); SetTextColor(lpDIS->hDC, 0x00A0FFFF); switch ( lpDIS->CtlID ) { case IDC_INFO: DrawIcon(lpDIS->hDC, (lpDIS->rcItem.right - lpDIS->rcItem.left + 8 - GetSystemMetrics(SM_CXICON))/2, lpDIS->rcItem.top + 5, LoadIcon(NULL, IDI_INFORMATION)); lpDIS->rcItem.top = lpDIS->rcItem.bottom - 20; DrawText(lpDIS->hDC, TEXT("O programu"), -1, &lpDIS->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER); break; case IDC_CHYBA: DrawIcon(lpDIS->hDC, (lpDIS->rcItem.right - lpDIS->rcItem.left + 8 - GetSystemMetrics(SM_CXICON))/2, lpDIS->rcItem.top + 5, LoadIcon(NULL, IDI_ERROR)); lpDIS->rcItem.top = lpDIS->rcItem.bottom - 20; DrawText(lpDIS->hDC, TEXT("Bug report"), -1, &lpDIS->rcItem, DT_SINGLELINE | DT_CENTER | DT_VCENTER); break; } DeleteObject(hbPozadi); } ///////////////////////////////////////////////////////////////////////////// // procedura dialogu INT_PTR CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch ( uMsg ) { case WM_COMMAND: switch ( LOWORD(wParam) ) { case IDOK: case IDCANCEL: DeleteObject(g_hbPozadi); EndDialog(hwndDlg, LOWORD(wParam)); break; case IDC_HONZA: ShellExecute(NULL, TEXT("open"), TEXT("http://www.rplusj.cz/index.asp?stranka=fotogalerie.htm"), NULL, NULL, SW_SHOWMAXIMIZED); break; case IDC_CHYBA: ShellExecute(NULL, TEXT("open"), TEXT("http://www.rplusj.cz/obrazek.asp?src=data/foto/sranda/kdyz_usa_prohraje.jpg"), NULL, NULL, SW_SHOWMAXIMIZED); break; case IDC_INFO: ShellExecute(NULL, TEXT("open"), TEXT("http://www.rcsoft.cz"), NULL, NULL, SW_SHOWMAXIMIZED); break; } break; case WM_DRAWITEM: On_DrawItem((LPDRAWITEMSTRUCT)lParam); break; case WM_INITDIALOG: On_InitDialog(hwndDlg); break; } return FALSE; }Doprovodný projekt je ke stažení zde: win_api_28.zip
Máte připomínku, dotaz nebo komentář k článku a souvisejícími tématy?
Copyright © 2021 Radek Chalupa