Jak to přesně uvnitř funguje, to Vám asi nevysvětlím, ale princip je celkem jednoduchý. Zobrazení na monitoru probíhá nějak tak, že někde v paměti je vyhrazen určitý prostor, kterému je dáno, že první jeho buňka (schválně nepíšu bajt, protože velikost této "buňky" závisí na způsobu zobrazení - barevné hloubce) nese informaci o tom, jak vypadá levý horní pixel na vašem monitoru, druhá je o pixelu hned vedle, atd. A HW (jedna část grafické karty) bez možnosti ovlivnění z Vaší strany neúnavně tyto buňky "překopírovává" na příslušné místi na Vaší obrazovce-stále dokola a velice rychle) Pokud pak Vy, vaším programem něco "kreslíte", pak posíláte instrukce, které ve svém důsledku mění právě obsah této, pro Vás neviditelné, části paměti. No a pokud toho kreslení je více, tak si představte: - nejprve do všech buněk nastavíte stejnou (podkladovou barvu), tj. provedete vymazání - nyní nakreslíte první čáru, - nakreslíte druhou čáru.... To vše, dle rychlosti Vašeho HW a složitosti výpočtů použitých pro vykreslování a v neposlední řadě i složitosti samotných vykreslovaných obrazců provádíte sice velmi rychle, ale ono "překopírovávání" obsahu grafické paměti na monitor probíhá ještě rychleji, takže se Vám dostane na monitor stav úplně čisté obrazovky, pak obrazovky s několika málo čárami a následně pak úplný obrázek. Přestože oko nezaznamená samotný proces vykreslování, rozdíl kontrastů je natolik velký, že máte ten známý pocit blikání. Tak se to vymyslelo trošku jinak. Do té vlastní grafické paměti uložíme informace o našem obrázku a ty jsou vesele periodicky překopírovávány na monitor, takže se nám zdá, že to svítí stále stejne. Necháme to svítit, a zatím si připravíme kus své paměti, který "naformátujeme" stejně, jako je naše zmiňovaná grafická paměť (to zřejmě dělá ten první příkaz v těch dvou):
CurCont = BufferedGraphicsManager.Current ' nastavíme kontext bufferu dle aktuálního systému
Buffer = CurCont.Allocate(Me.PictureBox1.CreateGraphics, Me.PictureBox1.Bounds) ' alokujeme pro buffer prostor (a navážeme na vykreslovací plochu
no a tím druhým příkazem určíme velikost té paměti (to je ten druhý parametr, který zadává velikost obdélníkové oblasti, která nás zajímá) a taky si nastavíme, kam pak budeme chtít vlastní obsah bufferu poslat (to je ten první parametr) No a pokud to máme takto všechno připravené, provádíme úplně stejné kreslení jako v prvním případě, jenomže nevykreslujeme do té části paměti, která se nám stále zobrazuje na monitoru (ta grafické paměť), ale vykreslujeme do té naší pomocné části paměti, která vypadá úplně stejně, umí úplně stejné věci jako ta grafická, jenom se nám nikam nevykresluje. Takže v klidu ji můžeme vymazat (nastavit jednotnou barvu pozadí), nakreslit první čátu, nakreslit druhou čáru,.... No a až jsme s výsledkem spokojeni (je třeba si uvědomit, že na monitoru nám stále "svítí" obsah té původní grafické paměti a doposud se na něm nezměnila ani čárka), takže až jsme spokojeni, zavoláme
Buffer.Render()
který najednou (na jeden zátah) obsah té naší pomogné paměti přesype do té "skutečně grafické", takže HW při dalším taktu začne na monitor promítat hned nový obrázek. Buď je to děláno takto (a ten obsah je skutečně kopírován, ale protože je to blokové kopírování souvislé části paměti, je to i při dnešních velkých rozlišení opravdu velmi rychlé), nebo existuje ještě doublebuffering např. při DirectX, kde to funguje podobně ale nic se nekopíruje. Tam to funguje tak, že si tu "obrazovou" paměť uděláte zcela identickou na místě, kam dosáhne přímo HW grafické karty, a uděláte si dvě (nebo i více) identických dvojčat a pak pouze měníte informaci o tom, které z dvojčat je právě "Fronfbuffer", a které "BackBuffer", tzn. ten frontBuffer se vykresluje na monitor a do tobo backbufferu můžete malovat Vy, tak jak jsme to naznačili výše. No a až jste spokojen, nic nekopírujete, jenom HW řeknete, že má odteď na monitor vykreslovat z toho druhého prostoru (kam jste doposud kreslil Vy) a naopak Vám se zpřístupní pro kreslení a úpravy ten prostor první (jinak řečeno bufery se nepřekopírují, ale překlopí, ten co byl doteď front bude back a naopak). Je zřejmé, že tento postup bude ještě mnohem rychlejší. A dokonce v tomto případě můžete mít těch "backbufferů" více - neptejte se mne ale k čemu :-) Tak to byla "trocha" teorie. S tím Vašim zvětšováním či nezvětšováním pictureboxu. Jednak je zapotřebí si uvědomit, a dle předchozího jste to asi pochopil, že velikost bufferu se musí rovnat velikosti zobrazované oblasti. Pokud tedy máte v úmyslu ponechat možnost změny velikosti cílové vykreslovací oblasti, musíte ten buffer vždy po takovéto změně znovu předefinovat, jinak se Vám bude překreslovat stále jen ta oblast původně zadaná. Jinak ještě drobnost, pokud máte picturebox dokovaný ve Formu a nemáte tam nic jiného, můžete kreslit přímo na Form, jedinou změnou bude definice grafické plochy, kde místo me.picturebox.creategraphics dáte jenom me.creategraphics - a samozřejmě i velikost bude odvozená z "me". Snad jse Vás moc neunavil a snad jsem to napsal aspoň trošičku sdělně - je to, samozřejmě, hodně zjednodušené, ale šlo o princip.
|