Kurz1 - Kapitola10

17. června 2007 v 16:08 | http://www.sweb.cz/kurz_evt/ |  Programování pro WinCE

3.4 Posuvníky

I potom, co jsme zjistili a nastavili správný počet řádků na displeji, nemůžeme si prohlédnout obsah celého bufferu. Jeho rozsah je mnohonásobně větší než možnosti, které nám dávají rozměry displeje kapesního počítače. Zobrazení většího množství souvislých dat v okně programu řeší operační systém Windows elegantně pomocí tzv. posuvníků.
Posuvníky znáte z běžného používání programů pro Windows. Jsou to pásky s šipkovými tlačítky na spodní a pravé straně okna, které umožňují rolování okna.
Vytvoření posuvníku v okně je velmi snadné - stačí o to požádat systém při vytváření okna. Ve funkci InitInstance je vložena funkce CreateWindow. Pokud v této funkci změníme třetí parametr tak, aby volání funkce bylo následující:
    hWnd = CreateWindow(szWindowClass, szTitle, WS_VISIBLE | WS_VSCROLL,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
Doplněním parametru WS_SCROLL se okno programu po přeložení změní takto:

obr. 19 Standardní posuvník okna
Bohužel, Windows CE považují nabídkový pruh za součást klientské oblasti okna a posuvník zasahuje i do nabídkového pruhu. Takový vzhled okna není obvyklý, ani my jej nebudeme akceptovat. Zrušte opět parametr WS_SCROLL. Musíme si vytvořit posuvník sami.
Jedna z možností je vytvořit si nové okno pokrývající klientskou oblast, které by mělo vlastní posuvníky. My vyzkoušíme jinou cestu - vytvoříme si posuvník jako dceřinné okno hlavního okna.
V lokálních proměnných funkce WndProc si doplníme statickou (posuvník budeme používat trvale) proměnnou handle posuvníku a další pomocné proměnné.
 // Pro posuvnik
static HWND hwndScroll;
SCROLLINFO si;
int nVertPoz;
Na konec zprávy WM_CREATE doplníme vytvoření samostatného okna s posuvníkem:
    // Pripravime si svisly posuvnik
hwndScroll = CreateWindow(TEXT("scrollbar"),NULL,
WS_CHILD|WS_VISIBLE|WS_TABSTOP|SBS_VERT,0,0,0,0,
hWnd,(HMENU) 1,hInst, NULL);
Na konec zprávy WM_SIZE doplníme možnost změny velikosti posuvníku (a jeho vykreslení na nových pozicích) při případné změně okna. Současně naplníme parametry ve struktuře SCROLLINFO potřebné pro činnost posuvníku:
    MoveWindow(hwndScroll,
rctKlient.right - GetSystemMetrics(SM_CXVSCROLL),rctKlient.top,
GetSystemMetrics(SM_CXVSCROLL), rctKlient.bottom - rctKlient.top,TRUE);
si.cbSize = sizeof(si);
si.fMask = SIF_RANGE | SIF_PAGE | SIF_POS;
si.nMin = 0;
si.nPos = 0;
// maximum zvyseno o nSloupce pro zobrazeni na delitelnych adresach
si.nMax = nMaxPocet - 1 + nSloupce;
// posledni radek na strance muze byt neuplny, proto -1
si.nPage = (nLinek-1)*nSloupce;
SetScrollInfo (hwndScroll,SB_CTL,&si,TRUE);
Pokud bychom nyní program přeložili, už se na obrazovce objeví svislý posuvník. Nebude však správně pracovat, protože není zajištěno zpracování zpráv, které posílá. Do WndProc doplníme další položku ve zpracování zpráv.
    case WM_VSCROLL:
si.cbSize = sizeof(si);
si.fMask = SIF_ALL;
GetScrollInfo(hwndScroll,SB_CTL,&si);
nVertPoz = si.nPos;
switch (LOWORD(wParam))
{
case SB_TOP:
si.nPos = si.nMin;
break;
case SB_BOTTOM:
si.nPos = si.nMax;
break;
case SB_LINEUP:
si.nPos -= nSloupce;
break;
case SB_LINEDOWN:
si.nPos += nSloupce;
break;
case SB_PAGEUP:
si.nPos -= si.nPage;
break;
case SB_PAGEDOWN:
si.nPos += si.nPage;
break;
case SB_THUMBTRACK:
si.nPos = si.nTrackPos;
break;
default: break;
}
// radek by mel zacinat na adresach v nasobcich poctu sloupcu
si.nPos = (si.nPos / nSloupce) * nSloupce;
si.fMask = SIF_POS;
SetScrollInfo(hwndScroll,SB_CTL,&si,TRUE);
GetScrollInfo(hwndScroll,SB_CTL,&si);
if (si.nPos != nVertPoz)
{
nZobrByte = si.nPos;
InvalidateRect(hWnd,NULL,TRUE);
}
break;
Hodnoty, které posuvník posílá v nižší polovině wParam, udávají požadovaný posun. Podle toho upravíme pozici posuvníku. Pozici dále zarovnáme na číslo dělitelné počtem sloupců a necháme nastavit novou pozici posuvníku - SetScrollInfo. Jestliže se pozice posuvníku skutečně změnila (kontrola pomocí GetScrollInfo), změníme proměnnou ukazující na zobrazovaný Byte a necháme obrazovku překreslit.
Protože zprávu WM_SCROLL nám může poslat pouze jediné okno, netestujeme, kdo nám ji zaslal, ale hned ji zpracováváme.
Posuvník je dostatečně chytrý na to, aby zpracoval i vstupy z klávesnice, které mu přijdou, a převedl je na jeho zprávy.
Po přeložení a spuštění by měl posuvník pracovat a my si můžeme konečně prohlédnout obsah celého našeho bufferu.

obr. 20 Okno s vytvořeným posuvníkem
Pokud bychom v globálních proměnných změnili inicializaci nSloupce na hodnotu 16 a spustili program na HPC Pro, měli bychom dostat výsledek jako na obr.:

obr. 21 Program se 16 sloupci na HPC Pro
Zde je již vidět, že velikost jezdce posuvníku se mění s poměrem velikosti stránky k celkovému rozsahu.
Na závěr zbývá vyřešit drobnou vadu programu. Tentokrát po sobě nebudeme dceřiné okno (posuvník) uklízet, i když jsme jej vytvořili my. Windows za nás při ukončení programu automaticky zruší všechna dceřinná okna.
Místo toho musíme ošetřit jiný problém. Při ztrátě fokusu ztratí posuvník vstup od klávesnice a přestane zpracovávat mačkání kurzorových tlačítek na přístroji. Protože hlavní okno fokus a tedy vstup z klávesnice nepotřebuje, doplníme do řady zpráv předání fokusu (pokud jej dostane) zpět na náš posuvník. Obdrží-li funkce WndProc fokus zprávou WM_SETFOCUS, předá jej oknu posuvníku funkcí SetFocus.
    case WM_SETFOCUS:
// Hlavni okno fokus nepotrebuje - vratime jej posuvniku
SetFocus(hwndScroll);
break;

Co bychom si měli z této lekce zapamatovat?

  • Posuvník okna je umístěn na celé klientské oblasti.
  • Problém posuvníku lze řešit vytvořením samostatného okna v klientské oblasti nebo vlastním posuvníkem.
  • Posuvník posílá zprávy WM_VSCROLL resp. WM_HSCROLL.
  • Získá-li okno fokus, obdrží zprávu WM_SETFOCUS.
  • Fokus mezi okny je možné programově přepínat.
 

Buď první, kdo ohodnotí tento článek.

Nový komentář

Přihlásit se
  Ještě nemáte vlastní web? Můžete si jej zdarma založit na Blog.cz.