|
realizarea de efecte de animatie este TImageList,definit in "imagelst.h"
|
səhifə | 14/18 | tarix | 12.09.2018 | ölçüsü | 1,36 Mb. | | #81721 |
| realizarea de efecte de animatie este TImageList,definit in "imagelst.h".
EXEMPLU: (vezi si OWL_ABC / owl26 ) Editati fila .cpp astfel:
#include
#include
#include
#define IDB_BITMAP1 1
#define IDB_BITMAP2 2
class Fer1 : Fer1();
~Fer1();
void Paint(TDC& dc,bool erase,Trect& rect);
TSize s1,s2;
TInageList* Imagine1;
TImageList* Imagine2; };
Fer1::Fer1():TWindow(0,0,0) {
Attr.X = 20;
Attr.Y = 20;
Attr.W = 480;
Attr.H = 480;
SetBkgndColor(RGB(250,250,220));
s1 = TSize(100,100);
s2 = TSize(10,10);
Imagine1 = new TImageList(s1,true,10,10);
Imagine2 = new TImageList(s2,true,10,10);
TBitmap img(*GetModule(),1);
TBitmap img2(*GetModule(),2);
Imagine1 -> Add(img);
Imagine2 -> Add(img2);
Imagine1 -> SetBkColor(RGB(250,250,250)); };
Fer1::~Fer1()
{ delete Imagine1;
delete Imagine2; };
void Fer1::Paint(TDC& dc,bool,TRect&)
{ Imagine1 -> Draw(0,dc,20,250,ILD_NORMAL);
Imagine2 -> Draw(0,dc,105,300,ILD_NORMAL);sleep(1);
Imagine2 -> Draw(0,dc,150,280,ILD_NORMAL);sleep(1);
Imagine2 -> Draw(0,dc,200,282,ILD_NORMAL);sleep(1);
Imagine2 -> Draw(0,dc,250,300,ILD_NORMAL);sleep(1);
Imagine2 -> Draw(0,dc,300,320,ILD_NORMAL);
MessageBox("SFARSIT","",MB_OK); };
class Aplicatie1 : public TApplication {
public: Aplicatie1() : TApplication() {};
~Aplicatie1(){};
void InitMainWindow(); };
void Aplicatie1 :: InitMainWindow()
{ MainWindow = new TFrameWindow(0,"text",new Fer1,true); };
int OwlMain(int,char* []){ return Aplicatie1().Run(); }
Eliminati din proiect fila .DEF (cu DeleteNode) si apoi editati fila
.rc astfel incat sa contina imaginile BitMap necesare.Puteti copia fila
owl26.rc,sau puteti utiliza o fila noua (cu desenele d-voastra).
-91-
Pentru a edita fila de resurse puteti utiliza orice fila de tip BitMap
(cu extensia .bmp) sau puteti utiliza editorul C++.In acest caz,alegeti
din meniul File optiunea New,apoi Resource Project si apoi Bitmap.Pentru
a specifica dimensiunile desenului si numarul de culori,alegeti la inceput
butonul Options si complectati in caseta de dialog paleta de culori (2,16,
sau 256) si dimensiunile (Width in Pixels: si Height in Pixels).Apoi
confirmati cu OK si din nou cu OK.La nevoie utilizati din meniul principal
optiunea Bitmap pentru a afisa paleta de culori si paleta de obiecte
pentru desenare.Apoi desenati imaginile dorite (la fel ca si in Paint din
Windows).In final,salvati fila cu extensia .bmp (in acelasi director in
care va fi utilizata).Realizati doua astfel de file .bmp.Apoi,pentru a
include cele doua file in fila de resurse .rc,executati in proiectul
dorit un dublu click stg pe fila .rc,apoi executati un click de mouse
drept pe dirctorul afisat (cel cu numele .rc) si alegeti Add to Project.
Dupa ce introduceti cele doua file,executati un dublu click pe fila .rc
si apoi pe semnul plus.Daca totul este corect,folderul .rc va contine:
--owl26.rc
|
- #define: IDB_BITMAP2 <2>
|
- #define: IDB_BITMAP1 <1>
|
- fila1.bmp (folder)
|
- fila2.bmp (folder)
Daca deschideti cele doua foldere si selectati fila BITMAP,in fereastra
din dreapta se va afisa desenul respectiv.Pentru exemplul owl26 am desenat
un tun si un proiectil,dar puteti utiliza orice desene doriti.
In final,compilati si construiti fiecare nod,apoi verificati toate le-
gaturile dintre module (cu LINK) si executati aplicatia.
Observati ca am definit si un destructor pentru fereastra Fer1.Pentru
a elimina cele doua desene,se poate apela direct destructorul.In cazul
in care desenele se vor utiliza in mod repetat,se va apela fie constructo-
rul fie destructorul.Observati ca si obiectul Aplicatie1 are un destructor
distinct.Practic,fiecare modul sau obiect din aplicatie are constructorul
si destructorul sau.Pentru a elimina din proiect doar un anumit modul,sau
doar un anumit obiect,se va apela destructorul respectiv.Pentru a elibera
complet memoria,se va apela destructorul obiectului de tip TApplication.
Deschideti fila si studiati obiectul TImageList.
Obiectul TImageList are opt constructori distincti,astfel incat permite o
gama foarte larga de implementari.Deasemenea,metoda Add() are supraincar-
cate patru variante diferite,astfel incat sa poata adauga imagini BitMap
sau Icon cat mai usor.Pentru desenarea obiectelor exista doua versiuni ale
metodei Draw,iar pentru deplasarea imaginilor contine metodele mecanismu-
lui de tip Drag and Drop (BeginDrag,DragEnter,DragMove,DragLeave,EndDrag).
In exemplul owl26 am utilizat cel mai simplu mecanism posibil.Observati
ca este necesara o procedura speciala pentru definirea contextului de
dispozitiv grafic.Prin conventie,aceasta procedura se denumeste Paint,
pentru a fi cat mai usor de identificat.Se pot adauga algoritmi pentru
deplasarea unuia dintre obiecte(sau a ambelor obiecte).Incercati sa adau-
gati un buton de culisare pentru reglarea tirului.
-92-
Pentru a crea senzatia de deplasare,se utilizeaza o imagine denumita
masca (mask) cu aceleasi dimensiuni,dar colorata in culoarea de fond.Masca
se va suprascrie peste imaginea anterioara,pentru a sterge "urmele".
EXEMPLU: (vezi si OWL_ABC / owl27 ) Editati fila .cpp astfel:
#include
#include
#include
#define IDB_BITMAP1 1
#define IDB_BITMAP2 2
class Fer1 : public TWindow {
public: Fer1();
~Fer1();
void Paint(TDC& dc,bool erase,TRect& rect);
TSize s1,s2;
TImageList* Imagine1; TImageList* Imagine2; };
Fer1::Fer1():TWindow(0,0,0) {
Attr.X = 20;Attr.Y = 20; Attr.W = 480; Attr.H = 480;
s1 = TSize(200,200); s2 = TSize(200,200);
Imagine1 = new TImageList(s1,true,10,10);
Imagine2 = new TImageList(s2,true,10,10);
TBitmap img(*GetModule(),1);
TBitmap img2(*GetModule(),2);
Imagine1 -> Add(img);
Imagine2 -> Add(img2);
Imagine2 ->SetBkColor(RGB(250,250,250)); };
Fer::~Fer1()
{ delete Imagine1;
delete Imagine2; };
void Fer1::Paint(TDC& dc,bool,TRect&)
{ Imagine1->Draw(0,dc,20,200,ILD_NORMAL);sleep(1);
Imagine2->Draw(0,dc,20,200,ILD_NORMAL);
Imagine1->Draw(0,dc,150,150,ILD_NORMAL);sleep(1);
Imagine2->Draw(0,dc,150,150,ILD_NORMAL);
Imagine1->Draw(0,dc,200,100,ILD_NORMAL);sleep(1);
Imagine2->Draw(0,dc,200,100,ILD_NORMAL);
Imagine1->Draw(0,dc,250,50,ILD_NORMAL); };
class Aplicatie1 : public TApplication {
public: Aplicatie1() : TApplication() {};
~Aplicatie1(){};
void InitMainWindow(); };
void Aplicatie1::InitMainWindow()
{ MainWindow = new TFrameWindow(0,"text",new Fer1,true); };
int OwlMain(int,char* []) { return Aplicatie1().Run(); }
Pentru fila .rc utilizati doua imagini de tip .bmp de aceeasi dimen-
siune(200/200),cea de a doua imagine fiind complet goala.
Eliminati fila .def,apoi compilati,construiti si executati obiectul.
Observati ca cea de a doua imagine practic suprascrie prima inagine,dupa
fiecare interval de o secunda.Daca nu se specifica o culoare pentru fond
(cu SetBkColor()),atunci inaginea va fi transparenta.Metoda Draw accepta
si urmatoarele stiluri: ILD_BLEND25,ILD_BLEND50,ILD_TRANSPARENT si eventual
ILD_OVERLAYMASK pentru a determina modul de suprapunere a imaginilor.
-93-
Pentru a putea deplasa imaginea cu ajutorul tastelor,se poate adauga o
metoda specializata de tipul EvKeyDown.
EXEMPLU: (vezi si OWL_ABC / owl28 ) Editati fila .cpp astfel:
#include
#include
#define IDB_BITMAP1 1
#define IDB_BITMAP2 2
int xxx=150;int yyy=150;int xxx1=150;int yyy=150;
class Fer1 : public TWindow {
public: Fer1(); ~Fer1();
void Paint(TDC& dc,bool,erase,TRect& rect);
void EvKeyDown(uint key,uint repeatCount,uint flags);
TSize s1,s2;
TImageList* Imagine1; TImageList* Imagine2;
DECLARE_RESPONSE_TABLE(Fer1); };
DEFINE_RESPONSE_TABLE1(Fer1,TWindow)
EV_WM_KEYDOWN,
END_RESPONSE_TABLE;
Fer1::Fer1(): TWindow(0,0,0) {
Attr.X = 20; Attr.Y = 20; Attr.W = 480; Attr.H = 480;
s1 = TSize(100,100); s2 = TSize(100,100);
Imagine1 = new TImageList(s1,true,10,10);
Imagine2 = new TImageList(s2,true,10,10);
TBitmap img(*GetModule(),1);TBitmap img2(*GetModule(),2);
Imagine1 -> Add(img);Imagine2 -> Add(img2);
Imagine2 -> SetBkColor(RGB(250,250,250)); };
Fer1::~Fer1() { delete Imagine1;delete Imagine2; };
void Fer1::Paint(TDC& dc,bool,Trect&)
{ Imagine1->Draw(0,dc,xxx,yyy,ILD_NORMAL); };
void Fer1::EvKeyDown(uint key,uint,uint)
{ TClientDC dc(*this); switch (key)
{ case VK_UP: xxx1=xxx;yyy1=yyy-50;
Imagine2->Draw(0,dc,xxx,yyy,ILD_NORMAL);
Imagine1->Draw(0,dc,xxx1,yyy1,ILD_NORMAL);break;
case VK_DOWN: xxx1=xxx;yyy1=yyy+50;
Imagine2->Draw(0,dc,xxx,yyy,ILD_NORMAL);
Imagine1->Draw(0,dc,xxx1,yyy1,ILD_NORMAL);break;
case VK_LEFT: xxx1=xxx-50;yyy1=yyy;
Imagine2->Draw(0,dc,xxx,yyy,ILD_NORMAL);
Imagine1->Draw(0,dc,xxx1,yyy1,ILD_NORMAL);break;
case VK_RIGHT: xxx1=xxx+50;yyy1=yyy;
Imagine2->Draw(0,dc,xxx,yyy,ILD_NORMAL);
Imagine1->Draw(0,dc,xxx1,yyy1,ILD_NORMAL);break; };
xxx=xxx1;yyy=yyy1; };
class Aplicatie1 : public TApplication {
public: Aplicatie1() : TApplication() {}; ~Aplicatie1() {};
void InitMainWindow(); };
void Aplicatie1::InitMainWindow()
( MainWindow = new TFrameWindow(0,"text",new Fer1,true); };
int OwlMain(int,char* []) { return Aplicatie1().Run(); }
In timpul executiei,utilizati tastele cu sageti pentru a deplasa imaginea.
-94-
Pentru deplasare,se pot utiliza si metodele "Drag and drop" astfel:
EXEMPLU: (vezi si OWL_ABC / owl29 ) Editati fila .cpp astfel:
#include
#include
#include
#define IDB_BITMAP1 1
int xxx=150;int yyy=350;int xxx1=150;int yyy1=150;
class Fer1 : public TWindow {
public: Fer1(); ~Fer1();
void Paint(TDC& dc,bool erase,TRect& rect);
void EvRButtonDown(uint,TPoint&);
TSize s1;
TImageList* Imagine1;
DECLARE_RESPONSE_TABLE(Fer1); };
DEFINE_RESPONSE_TABLE1(Fer1,TWindow)
EV_WM_RBUTTONDOWN,
END_RESPONSE_TABLE;
Fer1::Fer1():TWindow(0,0,0) {
Attr.X =20; Attr.Y = 20; Attr.W = 480; Attr.H = 480;
s1 = TSize(100,100);
Imagine1 = new TImageList(s1,true,10,10);
TBitMap img(*GetModule(),1);
Imagine1 -> Add(img); };
Fer1::~Fer1() { delete Imagine1; };
void Fer1::Paint(TDC& dc,bool,Trect&)
{ Imagine1 -> Draw(o,dc,xxx,yyy,ILD_NORMAL); };
void Fer1::EvRButtonDown(uint,TPoint&)
{ TClientDC dc(*this); xxx1=xxx;yyy1=yyy-50;
ShowCursor(FALSE);SetCapture();UpdateWindow();
Imagine1->SetDragCursorImage(0,0,0);
Imagine1->BeginDrag(0,0,0);
Imagine1->DragEnter(*this,xxx,yyy);
Imagine1->DragMove(xxx1,yyy1);sleep(2);
Imagine1->DragLeave(*this);Imagine1->EndDrag();
ReleaseCapture();ShowCursor(TRUE);xxx=xxx1;yyy=yyy1; };
class Aplicatie1 : public TApplication {
public: Aplicatie1() : TApplication() {};
~Aplicatie1(){};
void InitMainWindow(); };
void Aplicatie1::InitMainWindow()
{ MainWindow = new TFrameWindow(0,"text",new Fer1,true); };
int OwlMain(int,char* []){ return Aplicatie1().Run(); }
Compilati,construiti si executati exercitiul.La fiecare click de mouse
cu butonul drept,imaginea va fi deplasata timp de 2 secunde.La fiecare
click saltul va fi din ce in ce mai mare,deoarece se acumuleaza difernta
din variabila yyy1.
In acest exemplu,am utilizat evenimentul RButtonDown,dar se poate uti-
liza orice alt eveniment Windows.In multe situatii,metodele DRAG AND DROP
pot fi impartite in mai multe proceduri,astfel incat la apasarea butonului
sa se efectueze selectia imaginii,iar la eliberarea butonului sa se faca
deplasarea si operatiile de stergere pentru imaginea anterioara.
-95-
Pentru a aplica metodele DRAG AND DROP,este necesar ca imaginea sa fie
stocata temporar intr-un tampon de memorie.In acest exemplu,si in multe
alte situatii,s-a utilizat tamopnul de memorie destinat cursorului.Pentru
acest scop,cursorul a fost invalidat temporar (observati ca in timpul ope-
ratiei de DRAG cursorul dispare) iar imaginea a fost stocata temporar cu
SetDragCursorImage().Dupa epuizarea operatiilor,cursorul trebuie reactivat
cu ShowCursor(True).Acest gen de implementare este foarte avantajos,pentru
ca nu necesita alocarea de memorie suplimentara,dar prezinta si un mic
inconvenient.In situatiile in care aplicatia se blocheaza in timpul unei
operatii de DRAG,cursorul este invalidat si aplicatia nu poate fi depanata
sau actualizata.Singura solutie este oprirea si repornirea calculatorului.
Operatiile de grafica animata nu ridica probleme atunci cand se lucreza
cu o singura imagine grafica.Pe masura ce se utilizeaza tot mai multe
obiecte si imagini grafice,memoria de operare devine din ce in ce mai
incarcata iar la un anumit moment dat,incep sa apara suprascrieri.Din
acest motiv,trebuie tinuta o evidenta foarte stricta a operatiilor efec-
tuate si o gestiune/operatie a memoriei consumate.Obiectele care nu mai
sunt necesare de loc,vor fi eliberate complet apeland destructorul,iar
cele care urmeaza sa fie utilizate din nou,vor fi doar inactivate temporar
sau vor fi pur si simplu suprascrise (sterse prin suprapunerea unui alt
obiect grafic).Este bine sa lasati o marja de siguranta,astfel incat dupa
ce calculati toate operatiile ce urmeaza sa fie executate,sa mai ramana
inca suficient loc in memoria de operare si pentru restul variabilelor,
pentru gestiunea proceselor,pentru expandarea unor obiecte sau baze de
date etc.Nu va lansati la operatii foarte complexe.Este bine sa verificati
pas cu pas,fiecare operatie introdusa in program.Dupa fiecare etapa rezol-
vata,efectuati o copie de siguranta a proiectului,astfel incat sa puteti
reveni cat mai usor la o atapa anterioara de dezvoltare.Uneori,de la un
anumit punct,se vor putea ramifica mai multe variante,dintre care urmeaza
sa alegeti varianta cea mai buna,in functie de evolutia ulterioara a
proceselor (este greu de anticipat care va fi solutia cea mai buna).
Pentru programele si aplicatiile mari,este bine lucrati modular.Fiecare
astfel de modul,va fi mult mai usor de depanat,dar mai ales,va putea fi
utilizat in mai multe programe.In timp,prin cumularea acestor module,pro-
gramarea unei aplicatii noi va fi asemenatoare cu un joc de "puzzle" in
care nu trebuie decat sa alegeti piesele de care aveti nevoie pentru a
realiza tabloul complet.
Dupa adaugarea fiecarui modul,compilati,executati si eventual depanati
programul.Daca adaugati mai multe module dintr-un singur pas,va fi mult
mai greu de verificat legaturile si eventualele situatii de supraincarcare
a unor identifcatori sau definitii.Verificati cu atentie fiecare modul.
Chiar daca modulul functioneaza perfect in alta aplicatie,este posibil ca
in programul d-voastra sa nu functioneze,sau sa functioneze incorect.De
obicei este o problema legata de "mediul de operare".Cu alte cuvinte,in
spatiul de vizibilitate comuna exista doi sau mai multi identificatori
"supraincarcati",sau pur si simplu exista mai multe obiecte care exploa-
teaza competitiv aceleasi mesaje Windows,aceleasi tampoane de memorie sau
aceiasi registri de procesor.Prin adaugarea succesiva a modulelor,ope-
ratiile de verificare si control vor fi mult mai usor de realizat.
Dupa ce programul merge "perfect",rugati un cunoscut sau un coleg sa-l
verifice.In multe cazuri va descoperii "lacune" la care nu v-ati gandit.
-96-
Pentru a repeta unele operatii la intervale mai mici de o secunda,se
pot utiliza cronometrele.In OWL,cronometrul este inclus in fereastra de
tip TWindow cu ajutorul functiei SetTimer (urmata de KillTimer).
EXEMPLU: (vezi si OWL_ABC /owl30 ) Editati fila .cpp astfel:
#include
#include
#define IDB_BITMAP1 1
#define IDB_BITMAP2 2
int xxx=150;int yyy=350;int xxx1=150;int yyy1=150;
class Fer1: public TWindow {
public: Fer1();~Fer1();
void Paint(TDC& dc,bool erase,TRect& rect);
void EvTimer(uint id);
TSize s1,s2;
TImageList* Imagine1;TImageList* Imagine2;
DECLARE_RESPONSE_TABLE(Fer1);
DEFINE_RESPONSE_TABLE1(Fer1,TWindow)
EV_WM_TIMER,
END_RESPONSE_TABLE;
Fer1::Fer1():TWindow(0,0,0) {
Attr.X = 20;Attr.Y = 20;Attr.W = 480;Attr.H = 480;
s1 = TSize(100,100); s2 = TSize(100,100);
Imagine1 = new TImageList(s1,true,10,10);
Imagine2 = new TImageList(s2,true,10,10);
TBitmap img(*GetModule(),1); TBitmap img2(*GetModule(),2);
Imagine1 -> Add(img); Imagine2 -> Add(img2);
Imagine2 -> SetBkColor(RGB(250,250,250)); };
Fer1::~Fer1() { delete Imagine1; delete Imagine2;KillTimer(1); };
void Fer1::Paint(TDC& dc,bool,TRect&)
{ Imagine1 -> Draw(0,dc,xxx,yyy,ILD_NORMAL);
SetTimer( 1,50); };
void Fer1::EvTimer(uint)
{ TClientDC dc(*this);
xxx1=xxx;yyy1=yyy-1;
Imagine2 ->Draw(0,dc,xxx,yyy,ILD_NORMAL);
Imagine1 ->Draw(0,dc,xxx1,yyy1,ILD_NORMAL);
xxx=xxx1;yyy=yyy1; };
class Aplicatie1 : public TApplication {
public: Aplicatie1() : TApplication() {};
~Aplicatie1(){};
void InitMainWindow(); };
void Aplicatie1::InitMainWindow()
{ MainWindow = new TFrameWindow(0,"text",new Fer1,true); };
int OwlMain(int,char* []){ return Aplicatie1().Run(); }
Compilati,construiti si executati.Functia KillTimer() a fost amplasata in
destructorul ferestrei Fer1,astfel incat operatiile incluse in procedura
EvTimer se vor repeta atat timp cat fereastra este deschisa (desenul se
va deplasa in sus,la fiecare 50 de milisecunde.Fiecare "timer" are un
numar de ordine,astfel incat sa se poata utiliza simultan mai multe crono-
metre.Atentie la destructori.Orice cronometru neinchis va executa operatii
in fundal,pana la inchiderea calculatorului(consuma memoria de RAM).
-97-
In Win32 nu se pot utiliza simultan mai mult de 32 de cronometre,dar
in sistemele mai mari(Millenium,XP etc.) numarul de cronometre poate fi
mai mare(64-256 in functie de tipul partitiei).Cronometrele se pot utiliza
si pentru procese cu executie multifilara (fiecare cronometru controleaza
1>2>
Dostları ilə paylaş: |
|
|