WinForms - Screensaver a kreslení pomocí GDI+
Co tento článek ukazuje
- Jak vytvářet screensavery v .NETu
- Jak pomocí objektově orientovaného programování vytvářet "lepší" aplikace
- Základy kreslení na obrazovku pomocí GDI+
Screensaver s červíky
V tomto článku vytvoříme screensaver na kterém se budou po obrazovce pohybovat "červíci". Červík je objekt který má barvu a pozici a oboje se může měnit. Červík se v každém kroku nakreslí (jako kruh) a posune se. Po nakreslení se ještě smaže část okna a to tak, že se přes okno nakreslí na náhodá místa několik černých kružnic, které tak smažou dříve nakreslené červíky. Pomocí objektového návrhu vytvoříme dva různé typy červíka a každý se bude chovat jinak, ale v hlaní aplikaci s nimi bude možné pracovat stejným způsobem (takže by nebyl problém přidat například třetí typ).
Jak funguje screensaver?
Screensaver je obyčejný spustitelný soubor, jenom má místo připony exe
příponu scr
. Program se spouští několika různými způsoby, podle
toho co chce uživatel dělat a tento způsob je aplikaci předán jako parametr
příkazové řádky. Pokud se screensaver normálně spouští je na příkazové řádce
předán parametr /s
. Při kliknutí na tlačítko "Nastavení" je
screensaveru předán parametru /c
. Poslední parametr a to /p
je aplikaci předán když se má kreslit náhled (v nastavení screensaveru ve windows).
(Zpracování posledního parametru vyžaduje znalost WinAPI, takže se jím zde nebudeme zabývat, nicméně kód který jej obsluhuje naleznete například v aplikaci [1])
static void Main(string[] args) { if (args.Length==0||args[0].StartsWith("/s")) // Spustit screensaver else if (args[0].StartsWith("/c")) // Nastaveni screensaveru else if (args[0].StartsWith("/p")) // Vykreslovani nahledu }
Po spuštění screensaveru je také potřeba, aby hlavní formulář aplikace zabral prostor celé obrazovky. Nejsnadnější způsob jak toho dosáhnout je vytvořit maximalizovaný formulář bez okrajů (a také je třeba skrýt ukazetel myši).
// Bez okraje, maximalizovany a skryt mys
FormBorderStyle=FormBorderStyle.None;
WindowState=FormWindowState.Maximized;
Cursor.Hide();
Objektový návrh aplikace
Pomocí objektově orientovaného programování je možné snadno vytvořit několik
typů "červíka", se kterými bude aplikace moci pracovat stejným způsobem,
ale jednotlivé objekty se budou chovat odlišně (v OOP terminologii se toto
nazývá polymorfismus). Vytvoříme si nejprve bázovou třídu Cervik
,
která bude obsahovat to co je pro všechny červíky společné a poté vytvoříme
třídy CervikJedna
a CervikDva
, které budou odvozené
od bázové třídy a budou do ní doplňovat specifické chování (pohyb a změnu barvy).
Objekty pro práci s červíky jsou graficky znázorněné na následujícím diagramu:
// Bazova trida - Zdedene tridy
// musi doplnit zmenu pozice a barvy public abstract class Cervik { // Pozice, velikost a barva protected Point Position; protected Size Size; protected Color CurrentColor; #region Abstraktni metody // musi byt implementovane v odvozene tride
// Tato metoda meni pozici a velikost cervika // - parametry width a height urcuji velikost okna // (aby cervik nevylezl mimo obrazovku) protected abstract void ChangePosAndSize(int width,int height); // Tato metoda meni barvu cervika - protected abstract void ChangeColor(); #endregion // Kresli cervika a zavola virtualni // metody na posunuti a zmenu barvy public void DrawFrame(Graphics gr,int width,int height) { // kresleni (bude popsano pozdeji)... // zmenit pozicic a barvu ChangePosAndSize(width,height); ChangeColor(); } }
Pro kompletní zdrojový kód se podívejte do přiloženého zdrojového kódu.
Třída Cervik
obsahuje dvě abstraktní virtuální metody
(virtuální znamená, že je možné měnit její chování a abstraktní znamená,
že ve třídě Cervik
nemá žádné tělo). Tyto dvě metody
jsou volány z DrawFrame
, protože v odvozených třídách
již budou tyto metody implementované a bude tedy možné je volat. Pomocí těchto
dvou metod dáváme najevo co je potřeba v odvozených třídách doplnit za
chování aby "červík" mohl fungovat tak jak má. Jakmile tedy při psaní odvozených
tříd doplníme tyto dvě metody, získáme funkčního "červíka" a nebude nutné
znovu psát metodu DrawFrame
, která obsatrává kreslení na obrazovku
(které bude vždy stejné).
// Prvni cervik - Ukazuje jak vytvorit funkcniho cervika public class CervikJedna : Cervik { // Implementace zmeny pozice protected override void ChangePosAndSize(int width,int height) { // TODO: Zmenit pozici cervika Position.X+=1; Position.Y+=1; } // Implementace zmeny barvy protected override void ChangeColor() { // TODO: Zmenit barvu cervika CurrentColor=Color.Red; } }
Kompletní kód opět hledejte v přiloženém souboru.
Jak jsem již psal, je možné tímto způsobem vytvořit několik různě se
chovajících tříd, které se ale mohou tvářit jako základní třída Cervik
.
Tímto způsobem je také možné s třídami pracovat, takže při vytváření formuláře
uložíme různé typy červíků v poli a při kreslení již budeme volat kreslení
červíka aniž bychom věděli se kterou třídou pracujeme.
// Do pole cerviku lze dat ruzne typy Cervik[] cervici=new Cervik[2]; cervici[0]=new CervikJedna(); cervici[1]=new CervikDva(); // Ale pri kresleni s nimi lze pracovat jednotne foreach(Cervik worm in cervici) worm.DrawFrame(gr,width,height);
Kreslení červíků
V článku jsem zatím nezmínil jak funguje samotné kreslení na obrazovku, takže je
na čase to napravit. Vzhledem k tomu, že se jedná o screensaver (se stále se měnícím
obsahem) je potřeba kreslit na obrazovku co nejčastěji, proto je upravená metoda
Main
tak, aby se stále v cyklu volala metoda obstarávající kreslení.
Pro samotné kreslení je nejprve potřeba získat objekt Graphics
pro
kreslení na hlavní formulář. K tomu slouží metoda CreateGraphics
.
Tento objekt je také po dokončení kreslení nutné uvolnit (a to zavoláním metody
Dispose
). K tomuto slouží v C# konstrukce using
:
using(Graphics gr=CreateGraphics()) { // Zde se provede kresleni... } // Po opusteni bloku using se vola gr.Dispose()
Samotné kreslení červíků je poměrně jednoduché, protože se kreslí pouze
kružnice různých barev (při kreslení červíka) a nebo černé kružnice
při mazání. Při kreslení barevných kružnic je nejprve potřeba
vytvořit Brush
(štětec) dané barvy pomocí kterého se bude
kreslit. Tento objekt má metodu Dispose
, kterou je nutné
po dokončení kreslení zavolat (u objektů na kreslení je většinou nutné
volat Dispose
, protože tyto objekty je potřeba uvolnit co nejdříve).
Kreslení barevné kružnice vypadá tedy takto:
// kresli na aktualni pozici pomoci aktualni barvy using(Brush br=new SolidBrush(CurrentColor)) { // Vykresli se kruznice se stredem v bode // Positon a velikosti urcenou pomoci Size gr.FillEllipse(br,Position.X-Size.Width/2, Position.Y-Size.Height/2,Size.Width,Size.Height); }
Soubory na stažení a odkazy
- [1] Fractal Snow screensaver [^] - Obsahuje zpracování parametru /p - kreslení náhledu