GrafickΘ aplikace ve Visual C++ (2.)
I p°es vÜechny nev²hody GDI, je ve Windows tak°ka vÜudyp°φtomnΘ.
JakΘkoliv kreslenφ ve Windows je dφlem prßv∞ GDI. Myslφm, ₧e princip
GDI je pot°eba alespo≥ ΦßsteΦn∞ chßpat pro ·plnΘ pochopenφ DirectDraw.
Ve skuteΦnosti na tom nic nenφ. Pot°ebujete v∞d∞t, co jednotlivΘ
funkce ve skuteΦnosti d∞lajφ.
2.1. Funkce OnDraw()
Funkce OnDraw() je jedna z nejd∙le₧it∞Üφch funkcφ GDI.
VßÜ program jφ automaticky
volß poka₧dΘ, kdy₧ chce p°ekreslit okno tzn. p°i zm∞n∞ velikosti,
maximalizaci nebo minimalizaci okna atd. Jednß se o Φlenskou funkci
t°φdy pohledu CView . P°ijφmß jeden parametr a to je prßv∞ ukazatel
na kontext za°φzenφ (DC) vaÜeho okna. Funkce kontextu za°φzenφ
zapouzd°uje jinß t°φda CDC . Pomocφ tohoto parametru m∙₧ete
provßd∞t veÜkerΘ kreslenφ do okna.
NejjednoduÜÜφ °eÜenφ je, ₧e zapφÜete vßÜ k≤d p°φmo do tΘto funkce,
p°φpadn∞ si vytvo°φte vlastnφ funkci, kterß bude mφt jako parametr
ukazatel na DC a budete ji volat z funkce OnDraw() .
2.2. Jednoduch² p°φklad kreslenφ do okna
Vytvo°te si standardnφ projekt SDI (Single Document Interface)
MFC pomocφ AppWizardu.
Najd∞te funkci OnDraw() ve t°φd∞ pohledu CView. VaÜe t°φda pohledu
se samoz°ejm∞ jmenuje podle jmΘna projektu nap°. projekt Pepa bude
mφt t°φdu pohledu CPepaView.
Funkce CPepaView::OnDraw() po vygenerovßni AppWizardem:
void CPepaView::OnDraw(CDC* pDC)//ukazatel na kontext za°φzenφ
vaÜeho okna
{
CGDIDoc* pDoc = GetDocument();//ukazatel na vᚠdokument tzn.
na CPepaDoc
ASSERT_VALID(pDoc);//ov∞°enφ pDoc
// TODO: add draw code for native data here
}
P°epiÜte funkci nßsledovn∞:
void CPepaView::OnDraw(CDC* pDC)
{
CGDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//deklarace promenych
CRect client, user;
CPen pen;
//tato funkce vrati velikost okna pohledu
GetClientRect(&client);
// vytvori pero o urcite sirce a barve
pen.CreatePen(PS_SOLID, 5, RGB(255,0,0));
//od kazde souradnice odectu 25 pixelu
user.top = client.top + 25;
user.left = client.left + 25;
user.right = client.right - 25;
user.bottom = client.bottom - 25;
pDC->SelectObject(&pen); //vybere nase pero do kontextu zarizeni
pDC->Rectangle(&user); // tato funkce nakresli obdelnik
//napise text doprostred okna
pDC->TextOut(client.right / 2, client.bottom / 2, "GDI v praxi");
}
Program nakreslφ do okna Φerven² obdΘlnφk a doprost°ed napφÜe text.
Do kontextu za°φzenφ v₧dy kreslφte prßv∞ vybran²m tzv. GDI
objektem jako jsou pera, Üt∞tce, fonty, bitmapy atd. Tyto
objekty jsou v MFC za prvΘ p°edem p°ipraveny jako Stock
Objects a za druhΘ si je m∙₧ete vytvo°it samy, co₧ je
samoz°ejm∞ b∞₧n∞jÜφ zp∙sob prßce z GDI objekty.
2.3. GDI objekty
GDI objekty zapouzd°uje n∞kolik t°φd (my si uvedeme jen ty nejb∞₧n∞jÜφ) :
Pero
CPen - t°φda, ze kterΘ se vytvo°φ pero o danΘm typu, Üφ°ce a barv∞. Perem
kreslφme Φßry r∙znΘ tlouÜ¥ky a typu.
Postup vytvo°enφ pera :
-
Vytvo°φte objekt typu CPen
-
Zavolßte Φlenskou funkci t°φdy CPen::CreatePen()
Takto vypada deklarace funkce pro vytvo°enφ pera:
BOOL CreatePen(int nPenStyle, int nWidth, COLORREF crColor);
-
nPenStyle - styl pera m∙₧e b²t nap°φklad:
-
nWidth - Üφ°ka pera je celoΦφselnß hodnota v pixelech (v²Üe
uvedenΘ typy per krom∞ PS_SOLID fungujφ pouze je-li Üφ°ka
pera 1 pixel).
-
crColor - barva pera. Tento parametr se p°edßvß pomocφ makra RGB,
kterΘ p°ijφmß t°i hodnoty barev RGB (Red, Green, Blue) v rozsahu 0 - 255
nap°. kdy₧ napφÜete RGB(255,0,0) funkce vytvo°φ syt∞ ΦervenΘ pero.
Tento objekt jsme pou₧ili ve v²Üe uvedenΘm p°φkladu.
èt∞tec - Brush
CBrush - t°φda, kterß vytvo°φ Üt∞tec pro vykreslovßnφ velk²ch
ploch v okn∞ libovolnou barvou nebo vzorem.
Postup vytvo°enφ Üt∞tce :
-
Vytvo°φte objekt typu CBrush
-
Zavolßte Φlenskou funkci t°φdy CBrush::CreateSolidBrush() .
Funkce CreateSolidBrush() vytvo°φ Üt∞tec o jednΘ barv∞ tzn. ₧e
mß jeden parametr, kter² se zadßvß podobn∞ jako u pera pomocφ makra RGB.
Font
CFont - t°φda, kterß vytvo°φ font pro psanφ do okna. M∙₧ete si
vytvo°it zcela vlastnφ font, ale myslφm, ₧e spφÜe vyu₧ijete
font∙, kterΘ jsou nainstalovanΘ ve Windows.
Postup vytvo°enφ fontu :
-
Vytvo°φte objekt typu CFont
-
Zavolßte Φlenskou funkci t°φdy CFont::CreatePointFont() ,
kterß mß nßsledujφcφ parametry :
-
velikost fontu v desetinßch bodu tzn. pokud chcete pφsmo
o velikosti 12 bod∙ musφte zadat tento parametr 120
-
tvß° (face) fontu. Tento parametr je °et∞zec, kter² obsahuje
jmΘno vybranΘho fontu tzn. pokud chcete Arial dosadφte "Arial"
nebo "Times New Roman" pro Times New Roman. Pokud nenφ vßmi vybranΘ
pφsmo ve Windows program pou₧ije standardnφ pφsmo.
DalÜφmi GDI objekty jsou nap°φklad CBitmap,
CPalette nebo CRgn .
2.4. T°φda CDC
PotΘ, co si vytvo°φte sv∙j GDI objekt musφte ho vybrat do kontextu
za°φzenφ vaÜeho okna. To obstarß funkce t°φdy CDC::SelectObject() ,
kterß p°ijφmß ukazatel na vßÜ GDI objekt. Od tΘto chvφle se bude
kreslit vaÜφm perem nebo Üt∞tcem a psßt vaÜφm fontem. D∙le₧itΘ je,
₧e m∙₧e b²t vybrßn jen jeden objekt. Pokud tedy zavolßte opakovan∞
tuto funkci, p°edchozφ objekt se vyjme a vlo₧φ se jin². Funkce
SelectObjekt() vracφ ukazatel p°edeÜl² vybran² objekt GDI.
T°φda CDC obsahuje velkΘ mno₧stvφ funkcφ pro kreslenφ, tak₧e je
nemohu vÜechny popsat.
Funkce pro objekt CPen :
CPoint MoveTo( int x, int y );
CPoint MoveTo( POINT point );
Tyto dv∞ funkce pouze p°esouvajφ aktußlnφ pozici odkud se bude p°φÜt∞
kreslit. Vracφ p°edeÜlou pozici.
BOOL LineTo( int x, int y );
BOOL LineTo( POINT point );
Tyto dv∞ funkce kreslφ do okna prßv∞ vybran²m perem Φßru. Kreslφ se z
aktußlnφ pozice p°edem nastavenΘ funkcφ MoveTo() na pozici urΦenou
parametry. Aktußlnφ sou°adnice se p°esouvß tam, kde skonΦφ pero
s kreslenφm. Vracφ nenulovou hodnotu pokud je ·sp∞Ünß jinak 0.
Poznßmka: VÜimn∞te si, ₧e ka₧dß funkce mß dv∞ varianty,
to umo₧≥uje C++ dφky p°et∞₧ovßnφ funkcφ (overloading). Vidφte, ₧e prvnφ varianta
p°ijφmß jednoduchΘ typy, zatφmco druhß varianta objekt
POINT respektive RECT .
To jsou objekty Win32 API. Ekvivalentnφ objekt v MFC je
CPoint respektive CRect .
Tento objekt za prvΘ uchovßvß informaci o sou°adnici bodu respektive obdΘlnφku a
za druhΘ obsahuje mnoho Φlensk²ch funkcφ, kterΘ podstatn∞
zjednoduÜujφ prßci programßtora.
BOOL Rectangle( int x1, int y1, int x2, int y2);
BOOL Rectangle( LPRECT lpRect);
Tyto funkce nakreslφ obdΘlnφk do okna vybran²m perem. Jako parametry
m∙₧ete zadat Φty° sou°adnice tzn. hornφ lev² roh a dolnφ prav² roh
nebo p°edßte ukazatel na objekt typu CRect
respektive RECT . Vracφ
nenulovou hodnotu pokud je ·sp∞Ünß jinak 0.
BOOL Ellipse ( int x1, int y1, int x2, int y2 );
BOOL Ellipse ( LPRECT lpRect );
Tyto funkce kreslφ obecn∞ elipsu, ale dß se s nφ samoz°ejm∞ nakreslit
i kru₧nice. Mß Φty°i parametry, kterΘ jsou vlastn∞ stejnΘ jako u
p°edeÜlΘ funkce. Vracφ nenulovou hodnotu pokud je ·sp∞Ünß jinak 0.
Funkce pro objekt CBrush
BOOL FillRect ( LPRECT lpRect, CBrush * pBrush );
Tato funkce trochu popφrß, co jsme si °ekli o vklßdßnφ objekt∙,
proto₧e p°ijφmß parametr typu CBrush , co₧ je jak jist∞ vφte GDI
objekt. No nevφm, jak to v²vojß°i MFC mysleli. Ka₧dopßdn∞ tato
funkce funguje tak, ₧e vyplnφ obdΘlnφkovou oblast prßv∞ tφm Üt∞tcem,
kter² je zadßn jako parametr a ne tφm, kter² je vybrßn v DC. Prvnφ
parametr je ukazatel na objekt typu CRect respektive
RECT .
BOOL FloodFill ( int x, int y , COLORREF crColor);
Tato funkce je velmi podobnß funkci ze starΘho Pascalu. ZaΦne
vypl≥ovat plochu od urΦenΘho bodu, dokud nenarazφ barvu urΦenou
parametrem crColor . Prvnφ dva parametry jsou ten bod a druhy ta
barva, kterß se op∞t zadßvß pomocφ makra RGB (viz v²Üe). Vypl≥uje
prßv∞ vybran²m Üt∞tcem. Vracφ nenulovou hodnotu pokud je ·sp∞Ünß
jinak 0.
Funkce pro objekt CFont
BOOL TextOut (int x, int y, CString& str );
Tato funkce napφÜe text v bod∞ o sou°adnicφchx a y .
Samotn² text je ulo₧en ve
t°etφm parametru typu CString respektive referenci na
CString .
PφÜe se prßv∞ vybran²m fontem a nßvratovß hodnota je stejnß jako
ve vÜech p°edchozφch p°φpadech.
T°φda CDC mß spoustu dalÜφch funkcφ. Pokud byste m∞li n∞jak²
specißlnφ zßjem, staΦφ napsat.
2.5. P°φklad
P°ipravil jsem pro vßs jednoduch² p°φklad, kter² pou₧ije vÜechny
v²Üe popsanΘ funkce. Je to standardnφ aplikace
MFC AppWizard [exe]. P°esn² postup, jak
vytvo°it tento typ aplikace najdete ve t°etφm kurzu tohoto dφlu
a vy akorßt upravφte funkci OnDraw() . Tento
p°φklad si m∙₧ete stßhnout z CD zde
nebo v sekci Downloads.
void CGDIView::OnDraw(CDC* pDC)
{
CGDIDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
//
// Procvicujeme funkce GDI
CRect rcClient;
// Ulozime si velikost okna
GetClientRect(&rcClient);
//
// 1. Vytvorme si objekt pera CPen
CPen penBlue;
penBlue.CreatePen(PS_SOLID, 2, RGB(0, 0, 255));
// 2. Vytvorme si objekt stetce CBrush
CBrush brushRed, brushGreen;
brushRed.CreateSolidBrush(RGB(255, 0, 0));
brushGreen.CreateSolidBrush(RGB(0, 255, 0));
// 3. Do tretice si vytvorime font CFont
CFont fontTimes;
fontTimes.CreatePointFont(120, "Times New Roman");
//
// Vybereme pero
pDC->SelectObject(penBlue);
// Nyni muzeme kreslit modrym perem
// 1. Vytvorime diagonalni caru
pDC->MoveTo(0, 0);
pDC->LineTo(rcClient.right, rcClient.bottom);
// 2. Nakreslime obdelnik
pDC->Rectangle(rcClient.left + 25, rcClient.top + 25,
rcClient.right - 25, rcClient.bottom - 25);
// 3. Nakreslime elipsu uprostred okna
pDC->Ellipse(rcClient.left + 50, rcClient.top + 50,
rcClient.right - 50, rcClient.bottom - 50);
// 4. Pouzijeme funkci FillRect() k vybarveni obdelnicku
// Vsimnete si, ze nevybirame stetec!!!
pDC->FillRect(CRect(150, 150, 200, 200), &brushGreen);
//
// Nyni jiz musime vybrat stetec do DC
pDC->SelectObject(brushRed);
// 5. Pouzijeme funkci FloodFill() k vybarveni obdelnicku
pDC->FloodFill(30, 30, RGB(0, 0, 255));
//
// 6. Nakonec vybereme font do DC a napiseme text doprostred okna
pDC->SelectObject(fontTimes);
pDC->TextOut(rcClient.right / 2, rcClient.bottom / 2, "GDI v praxi");
//
}
Poznßmka:
-
Zkuste si zmenÜit Φi zv∞tÜit okno. VÜimn∞te si, ₧e obsah
okna se nehezky p°ekresluje poka₧dΘ, kdy₧ zm∞nφte velikost okna.
To je dßno tφm, ₧e funkce OnDraw() je volßna poka₧dΘ, kdy₧ se
mß okno p°ekreslit a takΘ samoz°ejm∞ tφm, ₧e GDI je pomalΘ.
-
Jak vidφte u funkce FillRect() , nenφ pot°eba
vybφrat ₧ßdn² Üt∞tec, proto₧e se k vybarvenφ pou₧ije
Üt∞tec, kter² je dßn v druhΘm parametru.
-
Vzßp∞tφ ale vidφte, ₧e u funkce FloodFill()
ji₧ Üt∞tec vybrat musφme, jinak se pou₧ije tzv. NULL BRUSH, kter²
nenakreslφ v∙bec nic.
-
Text, kter² mß b²t uprost°ed okna, vlastn∞ nenφ p°esn∞ uprost°ed.
Zkuste program upravit tak, aby text byl poka₧dΘ uprost°ed. Je nutnΘ
do sou°adnic textu zahrnout takΘ velikost samotnΘho textu.
Takto vypadß okno naÜφ aplikace:
2.6. Zßv∞r
Tato Φßst vßs tedy seznßmila s ·pln²mi zßklady GDI a m∞li byste si
alespo≥ n∞co z toho pamatovat, aΦkoliv to v DirectDraw p°φmo nepou₧ijeme.
V DirectDraw budeme tu a tam pou₧φvat kontexty za°φzenφ, ale to uvidφte
a₧ v p°φÜtφ lekci.
V p°φÜtφ lekci u₧ zaΦneme skuteΦnΘ DirectDraw. Pokud byste m∞li n∞jakΘ
specißlnφ po₧adavky nebo cht∞li poradit, m∙₧ete mi napsat.
T∞Üφm se p°φÜt∞ nashledanou.
|