fuLoad - volby načtení. Úplný popis naleznete v dokumentaci, zde jen o některých
- LR_DEFAULTSIZE - použije výchozí rozměry ze systémové metriky a ignoruje hodnoty cxDesired a cyDesired
- LR_LOADFROMFILE - načítáme ze souboru s názvem, který je dán parametrem lpszName
- LR_LOADTRANSPARENT - všechny pixely s barvou stejnou jako první pixel (souřadnice 0,0) jsou nahrazeny systémovou barvou oken (COLOR_WINDOW)
- LR_MONOCHROME - načítáme černobíle
- LR_SHARED - handle je sdílené, pokud načítáme opakovaně stejný obrázek. Pokud tuto volbu neuvedeme, měli bychom "po použití" uvolnit paměť příslušnou funkcí (pro bitmapu DeleteObject, pro ikonu DestroyIcon, pro kurzor DestroyCursor). K tomu ještě poznámku, že toto sdílení je u funkcí LoadIcon a LoadCursor „nastaveno natvrdo“, proto při jejich použití žádné funkce type Deletexxxxx nevoláme.
Nyní se podívejme na praktickou demonstraci této funkce. V horní části dialogu jsou čtyři prvky "STATIC" (v editoru zdrojů jako "Picture", kde jako "Type" zvolíme Icon), kterým jsou ve funkci InitDialog přiřazeny handle ikon získané uvedenou funkcí:
// … kód funkce InitDialog
GetDlgItem(IDC_ICON16)->SendMessage(STM_SETICON,
(WPARAM)(HICON)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 16, 16, LR_SHARED));
GetDlgItem(IDC_ICON32)->SendMessage(STM_SETICON,
(WPARAM)(HICON)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 32, 32, LR_SHARED));
GetDlgItem(IDC_ICON48)->SendMessage(STM_SETICON,
(WPARAM)(HICON)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICON1),
IMAGE_ICON, 48, 48, LR_SHARED));
GetDlgItem(IDC_ICON_CUSTOM)->SendMessage(STM_SETICON,
(WPARAM)(HICON)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICON2),
IMAGE_ICON, 128, 96, LR_SHARED));
// ….
Jak vidíte, lze ikonu roztáhnout do libovolného rozměru, který pak bude mít při svém zobrazení.
Nyní si řekněme o další "rozšířené" funkci
BOOL DrawIconEx(
HDC hdc, // handle kontextu zařízení
int xLeft, // x-ová souřadnice levého horního rohu
int yTop, // y-ová souřadnice levého horního rohu
HICON hIcon, // handle ikony
int cxWidth, // délka ikony
int cyWidth, // výška ikony
UINT istepIfAniCur, // index obrázku v animovaném kurzoru
HBRUSH hbrFlickerFreeDraw, // handle štětce pozadí
UINT diFlags // volby kreslení
);
Tato funkce umožňuje kreslit ikony nebo kurzory, včetně jednotlivých obrázků animovaných kurzorů, jak napovídá parametr istepIfAniCur. Máme dále možnost specifikovat rozměry, do kterých je výsledný obrázek roztažen. Parametr hbrFlickerFreeDraw umožňuje redukovat případné blikání při překreslování ikony nebo kurzoru. Pokud je uveden platný handle na brush (štětec), systém použije tento štětec jako pozadí s tím, že vytvoří v paměti bitmapu s tímto pozadím, do ní nakreslí ikonu nebo kurzor a tuto bitmapu pak přímo kopíruje do kontextu zařízení.
Použití této funkce vidíte na spodní části dialogu z ukázkového příkladu, kde jsou nakresleny jednotlivé kroky animovaného kurzoru, načteného ze souboru. Celý kód je realizován v handleru zprávy WM_PAINT:
int xPos, yPos;
xPos = 20;
yPos = 200;
hicon = (HICON)LoadImage(AfxGetInstanceHandle(),
"anicur.ani", IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE | LR_SHARED | LR_LOADFROMFILE);
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 0, NULL, DI_NORMAL);
xPos += 50;
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 1, NULL, DI_NORMAL);
xPos += 50;
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 2, NULL, DI_NORMAL);
xPos += 50;
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 3, NULL, DI_NORMAL);
xPos += 50;
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 4, NULL, DI_NORMAL);
xPos += 50;
DrawIconEx(dc.m_hDC, xPos, yPos, hicon, 32, 32, 5, NULL, DI_NORMAL);
Na závěr tohoto článku si ještě ukážeme, jak oknu nastavit příslušný kurzor, s tím, že se přesvědčíme o možnosti záměny ikony a kurzoru. Jako kurzor tedy nastavíme ikonu načtenou ze zdrojů. Pro nastavení kurzoru oknu, přesněji řečeno třídě, ke které okno patří, použijme funkci SetClassLongPtr (popř. starší variantu SetClassLong, která však není kompatibilní s 64bitovou verzí Windows). Následující funkce nastaví oknu dialogu jako kurzor ikonu IDR_MAINFRAME s tím, že ji navíc roztáhne do velikosti 64 x 64 pixelů:
void CUkazkaDlg::OnButton1()
{
SetClassLongPtr(m_hWnd, GCLP_HCURSOR,
(LONG)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDR_MAINFRAME), IMAGE_ICON, 64,64, 0));
}
Druhá funkce použije jinou ikonu (konkrétně ikonu programu Microsoft Word 2000), načte ji černobíle a přiřadí oknu jako kurzor:
void CUkazkaDlg::OnButton2()
{
SetClassLongPtr(m_hWnd, GCLP_HCURSOR,
(LONG)LoadImage(AfxGetInstanceHandle(),
MAKEINTRESOURCE(IDI_ICON2), IMAGE_ICON, 64,64, LR_MONOCHROME));
}
Chceme-li vrátit oknu zpět výchozí kurzor, použijeme příslušný systémový kurzor:
void CUkazkaDlg::OnButton3()
{
SetClassLongPtr(m_hWnd, GCLP_HCURSOR, (LONG)LoadCursor(NULL, IDC_ARROW));
}
Ještě poznámku k "vrácení" výchozího kurzoru: V naší ukázce nastavujeme výchozí systémový kurzor, což v některých případech nemuselo být algoritmicky čisté. Pokud by náš modul byl částí nějakého rozsáhlejšího programu, mohlo by se stát, že dříve, než se nám okno "dostane do spárů", mu byl přiřazen nějaký specifický kurzor, a patřilo by tedy k dobrému vychování vrátit mu zase tento kurzor. Tuto možnost nám dává návratová hodnota funkce SetClassLongPtr, která vrací předchozí hodnotu příslušného parametru třídy, tedy v našem případě handle na kurzor. Znamenalo by to algoritmicky si ošetřit "první sáhnutí na kurzor", uložit si návratovou hodnotu funkce a při "rozloučení se s oknem" tuto hodnotu nastavit zpět jako kurzor.
Tolik prozatím k ikonám a kurzorům. V některém z příštích článků se můžeme podívat podrobněji na to, jak lze „pracovat“ přímo s daty ikon a kurzorů, získanými ze zdrojů programu.
Ukázkový příklad si můžete stáhnout zde: icon_cursor.zip