Sunteți pe pagina 1din 9

30

LABORATOR Nr. 11-12

Interfaa unei aplicaii n arhitectur document-reprezentare

1. Generai aplicaia Lab6 selectnd ca i tip de proiect MFC AppWizard (exe) i apoi, n
pasul 1, Single document i Document/View architecture support. Arhitectura Document /
Reprezentare ofer cadrul necesar realizrii majoritilor aplicaiilor Windows.
Rezultatul este o aplicaie Windows standard, avnd o bar de meniuri, o bar cu
instrumente i o zon pentru reprezentare.

AppWizard a generat clasele reprezentative ale unei aplicaii Windows n arhitectur


document-reprezentare, respectiv CLab6Doc i CLab6View.
Funcionarea unei aplicaii de acest fel este posibil prin folosirea a 3 funcii :
GetDocument, o funcie aparinnd clasei CView folosit pentru obinerea unui
pointer la obiectul aparinnd clasei document ;
UpdateAllViews, o funcie membr a clasei CDocument apelat ori de cte ori
modificarea unor date coninute n obiectul document face necesar redesenarea zonei folosite
pentru reprezentare ;
OnNewDocument, o funcie aparinnd clasei CDocument, folosit pentru
iniializarea datelor aparinnd obiectului document.

1.

Generai i reprezentai grafic o list de elemente grafice, segmente de dreapt sau cercuri,
coordonatele necesare fiind obinute folosind funcia de generare a numerelor aleatoare,
rand(). Pentru declanarea generatorului de numere aleatoare se folosete funcia srand()
apelat astfel:
srand((unsigned) time (NULL));
Funcia time() returneaz numrul de secunde care au trecut de la ora 0, 1 ianuarie 1970.
Pentru utilizarea funciei time() va trebui inclus la nceputul fiierului Lab6Doc.cpp fiierul
antet <time.h>.
Numrul generat va fi cuprins ntre 0 i RAND_MAX. Prototipurile funciilor rand() i
srand() precum i declaraia constantei RAND_MAX sunt n <stdlib.h>, care va trebui de
asemenea inclus.
Rezolvare pentru cazul n care se genereaz o list de segmente:

31
a. Copiai n directorul proiectului (Lab6) fiierele punct.h, punc.cpp, segment.h, segment.cpp,
element.h, elment.cpp, cerc.h i cerc.cpp. Adugai apoi proiectului fiierele copiate :

b. Modificai funciile desenez() astfel nct s foloseasc funcii MFC.


Deoarece funciile necesare reprezentrilor grafice au fost definite n cadrul unei aplicaii
Windows API, declaraiile i coninutul acestora se modific astfel :
void punct::desenez(CDC* pDC)
{
CPen lPen(PS_SOLID, 1, col);
// Selectez penita
CPen* pOldPen = pDC->SelectObject(&lPen);
pDC->MoveTo(x-4, y);
pDC->LineTo(x+4, y);

32
pDC->MoveTo(x, y-4);
pDC->LineTo(x, y+4);
// Revin la penita anterioara
pDC->SelectObject(pOldPen);
}
void segment::desenez(CDC* pDC)
{
CPen lPen(PS_SOLID, 1, col);
// Selectez penita
CPen* pOldPen = pDC->SelectObject(&lPen);
pDC->MoveTo(x, y);
pDC->LineTo(x+dx, y+dy);
// Revin la penita anterioara
pDC->SelectObject(pOldPen);
}
void cerc::desenez(CDC* pDC)
{
CPen lPen(PS_SOLID, 1, col);
// Selectez penita
CPen* pOldPen = pDC->SelectObject(&lPen);
pDC->Ellipse(x-r, y-r, x+r, y+r);
// Revin la penita anterioara
pDC->SelectObject(pOldPen);
}
void element::desenez(CDC* pDC)
{
p->desenez(pDC);
}
c. Adugai clasei Lab6Doc variabila baza de tip element *. Variabila va fi iniializat cu
NULL n constructorul clasei CLab6Doc.
CLab6Doc::CLab6Doc()
{
// TODO: add one-time construction code here
baza = NULL;
}
d. Modificai funcia OnNewDocument() din clasa CLab6Doc astfel nct s creeze o list
de segmente :

33
BOOL CLab6Doc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
// (SDI documents will reuse this document)
long culoare;
int x, y, dx, dy;
segment *s;
element *e;
delete baza; // Daca se genereaza repetat lista, la fiecare initializare ea trebuie distrusa.
culoare = RGB(0, 0, 255); // Desenez cu albastru
// Generez lista de segmente
// Pornesc generatorul de numere aleatoare:
srand((unsigned) time (NULL));
// Generez primul element din lista :
// Primul punct
x = rand()*500/RAND_MAX; // Pentru a avea valori intre 0 si 500
y = rand()*500/RAND_MAX;
// Al doilea punct
dx = rand()*500/RAND_MAX - x;
dy = rand()*500/RAND_MAX - y;
// generez segmentul corespunzator
s = new segment(x, y, culoare, dx, dy);
e = new element(s, 1);
baza = e;
// Reiau de 30 ori
int i;
for(i=1; i<30; i++) {
// Primul punct
x = rand()*500/RAND_MAX;
y = rand()*500/RAND_MAX;
// Al doilea punct
dx = rand()*500/RAND_MAX - x;
dy = rand()*500/RAND_MAX - y;
// generez segmentul corespunzator
s = new segment(x, y, culoare, dx, dy);
e->urm = new element(s, 1);
e = e->urm; // Avansez pe noul element
}
return TRUE;
}

34

Pentru a putea declara variabile de tip segment sau element, n Lab6Doc.h vor fi incluse
fiierele "segment.h" i "element.h".
e. Modificai funcia OnDraw() aparinnd clasei CLab6View astfel nct s realizeze
desenarea listei de segmente.
void CLab6View::OnDraw(CDC* pDC)
{
CLab6Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// TODO: add draw code for native data here
// Desenez lista de elemente
element *e;
e = pDoc->baza;
while (e != NULL) {
e->desenez(pDC);
e = e->urm;
}
}

2.

Adugai barei cu instrumente a aplicaiei dou butoane care s permit impunerea


tipului de figur geometric inclus n lista de elemente i apoi s genereze i s deseneze
lista.
Funciile de tratare a evenimentelor corespunznd acionrii celor dou butoane,
OnCerc() i OnLinie() vor fi incluse n clasa CLab6Doc. Dup adugarea funciilor de tratare
a evenimentelor generate de apsarea butoanelor adugate, tergei din corpul funciei
OnNewDocument() secvena de program care genereaz lista de segmente.
BOOL CLab6Doc::OnNewDocument()
{
if (!CDocument::OnNewDocument())
return FALSE;
// TODO: add reinitialization code here
if (baza != NULL) delete baza;
baza = NULL;
// (SDI documents will reuse this document)
return TRUE;
}
Soluie :
void CLab6Doc::OnCerc()
{

35
// TODO: Add your command handler code here
long culoare;
int x, y, r;
cerc *s;
element *e;
delete baza; // Distrug lista precedenta
culoare = RGB(0, 0, 255); // Desenez cu albastru
// Generez lista de cercuri
// Pornesc generatorul de numere aleatoare:
srand((unsigned) time (NULL));
// Generez primul element din lista
// Centrul
x = rand()*500/RAND_MAX; // Pentru a avea valori intre 0 si 500
y = rand()*500/RAND_MAX;
// Raza
r = rand()*250/RAND_MAX; // Pentru a avea valori intre 0 si 250
// generez cercul corespunzator
s = new cerc(x, y, culoare, r);
e = new element(s, 2);
baza = e;
// Reiau de 30 ori
int i;
for(i=1; i<30; i++) {
// Centrul
x = rand()*500/RAND_MAX;
y = rand()*500/RAND_MAX;
// Raza
r = rand()*250/RAND_MAX;
// generez cercul corespunzator
s = new cerc(x, y, culoare, r);
e->urm = new element(s, 2);
e = e->urm; // Avansez pe noul element
}
// Redesenez imaginea
UpdateAllViews(NULL, 0L);
}
void CLab6Doc::OnLinie()
{
// TODO: Add your command handler code here
long culoare;

36
int x, y, dx, dy;
segment *s;
element *e;
delete baza; // Distrug lista precedenta
culoare = RGB(0, 0, 255); // Desenez cu albastru
// Generez lista de segmente
// Pornesc generatorul de numere aleatoare:
srand((unsigned) time (NULL));
// Generez primul element din lista :
// Primul punct
x = rand()*500/RAND_MAX; // Pentru a avea valori intre 0 si 500
y = rand()*500/RAND_MAX;
// Al doilea punct
dx = rand()*500/RAND_MAX - x;
dy = rand()*500/RAND_MAX - y;
// generez segmentul corespunzator
s = new segment(x, y, culoare, dx, dy);
e = new element(s, 1);
baza = e;
// Reiau de 30 de ori
int i;
for(i=1; i<30; i++) {
// Primul punct
x = rand()*500/RAND_MAX;
y = rand()*500/RAND_MAX;
// Al doilea punct
dx = rand()*500/RAND_MAX - x;
dy = rand()*500/RAND_MAX - y;
// generez segmentul corespunzator
s = new segment(x, y, culoare, dx, dy);
e->urm = new element(s, 1);
e = e->urm; // Avansez pe noul element
}
UpdateAllViews(NULL, 0L);
}

3.

Adugai clasei CLab6Doc variabila n de tip int care s rein numrul de elemente de
generat (1<n<100). Pentru introducerea unei valori adugai meniului aplicaiei o
opiune, funcia de tratare a evenimentului realiznd afiarea unei ferestre modale
pentru introducerea valorii. Valoarea va fi iniializat cu 1 n constructorul clasei
CLab6Doc.

37

4.

Realizai o nou aplicaie n care figurile geometrice sunt desenate folosind mouse-ul.
Noua aplicaie ve folosi clasele punct, segment, cerc i element.

Pentru preluarea coordonatelor mouse-ului se va intercepta mesajul WM_LBUTTONDOWN.


Folosind ClassWizard se asociaz evenimentului o funcie, care va fi plasat n CLab6View.

Pentru scrierea funciei se vor aduga clasei CLab6Doc membrii date e_pct_2 i coord1
avnd tipurile int respectiv CPoint. Variabila e_pct_2 trebuie iniializat cu 0 n constructorul
clasei CLab6Doc.
void CLab6View::OnLButtonDown(UINT nFlags, CPoint point)
{
// TODO: Add your message handler code here and/or call default
CLab6Doc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
// variabila point contine deja coord. cursorului f. de coltul zonei client
if(pDoc->e_pct_2) {
// Generez segmentul de dreapta. In coord1 am primul capat.
int dx, dy;
element *e;
segment *s;
dx = point.x-pDoc->coord1.x;
dy = point.y-pDoc->coord1.y;
s = new segment(pDoc->coord1.x, pDoc->coord1.y, RGB(0, 0, 255), dx,dy);
if (pDoc->baza == NULL) { // e primul segment
e = new element(s, 1);
pDoc->baza = e;
}

38
else {
// Merg pe ultimul segment din lista
e = pDoc->baza;
while (e->urm != NULL) {
e = e->urm;
}
e->urm = new element(s, 1);
e = e->urm; // Avansez pe noul element
}
// Desenez segmentul curent
CDC *pDC;
pDC = GetDC();
e->desenez(pDC);
ReleaseDC(pDC);
// Mut coordonatele pct. 2 in pct. 1.
pDoc->coord1 = point;
}
else { // Nu se poate trasa inca
pDoc->coord1 = point;
pDoc->e_pct_2=1;
}
}

S-ar putea să vă placă și