Sunteți pe pagina 1din 8

Ministerul Educaţiei al Republicii Moldova

Universitatea Tehnică a Moldovei

Facultatea Calculatoare Informatica si Microelectronica

RAPORT
Lucrarea de laborator nr.3,4,5
Programarea in Windows

A efectuat:

A verificat:
lect., univ. Lisnic Inga

Chisinau 2017

Tema: Curbe Bezier. Principiile de lucru cu tastatura. Principiile de lucru cu mouse-ul


Scopul lucrarii:
1. De a studia primitivele grafice ce permit afişarea curbelor Bezier şi afişarea acestor curbe cu ajutorul
formulelor.
2. De a studia metodele şi principiile de lucru cu tastatura. Însuşirea modului de prelucrare a mesajelor
parvenite de la tastatură
3. De studiat metodele şi principiile de lucru cu mouse-ul; de însuşit modul de prelucrare a
mesajelor parvenite de la mouse

Sarcina de lucru:
1. Scrieţi un program care afişază curba Bezier, utilizând funcţiile GDI standarde şi o curbă Bezier,
afişată după calcule prin formule.
2. De scris un program care în zona clienbt afişează un desen, care poate fi mişcat cu ajutorul tastelor
← (la stânga), ↑(în sus), →(la dreapta), ↓(în jos). De asemenea, trebuie să fie prevăzute taste pentru
rotirea figurii
3. 1. De modificat programul din lucrarea de laborator nr. 3 astfel ca punctele de control al
curbei Bezier să poată fi deplasate, schimbînd forma curbei în timp real.
2. De modificat programul din lucrarea nr. 4 astfel ca desenul să poată fi mişcat cu ajutorul mouse-lui.

Notiuni teoretice
Funcţiile Bezier sunt considerate utile pentru proiectarea asistată de calculator, datorită câtorva
caracteristici:
• În primul rând, cu puţină practică, de obicei puteţi să manipulaţi curba până ajunge la o formă
apropiată de cea dorită.
• În al doilea rând, curbele Bezier sunt foarte uşor de controlat. În unele variante ale funcţiilor spline,
curba nu trece prin nici unul din punctele care o definesc. Curbele Bezier, însă, sunt întotdeauna ancorate
în cele două puncte finale. (Aceasta este una dintre ipotezele de la care porneşte calculul formulei Bezier.)
De asemenea, unele forme ale funcţiilor spline au puncte de singularitate, din care curba se întinde la
infinit. În proiectarea asistată de calculator acest lucru este de cele mai multe ori evitat. Ca urmare, curbele
Bezier sunt întotdeauna limitate de un patrulater (numit „carcasă convexă" - „convex hull") format prin
unirea punctelor finale şi a punctelor de control.
• În al treilea rând, o altă caracteristică a curbelor Bezier implică relaţiile dintre punctele finale şi
punctele de control. Curba este întotdeauna tangentă la linia trasată de la primul punct final la primul
punct de control şi are întotdeauna aceeaşi direcţie cu această linie. (Această caracteristică este ilustrată
vizual de programul BEZIER.) De asemenea, curba este întotdeauna tangentă la linia trasată de la al doilea

1
punct final la al doilea punct de control şi are întotdeauna aceeaşi direcţie cu această linie. (Acestea sunt
alte două ipoteze de la care este derivată formula Bezier.)
• În al patrulea rând, curbele Bezier sunt satisfăcătoare şi din punct de vedere estetic. Ştiu că acesta
este un criteriu subiectiv, dar nu este numai părerea mea.
Arhitectura bazată pe mesaje a sistemului de operare Windows este ideală pentru lucrul cu tastatură.
Programul „află" despre apăsarea unor taste prin intermediul mesajelor care ajung la procedura de
fereastră. De fapt, lucrurile sunt puţin mai complicate: atunci când utilizatorul apasă şi eliberează tastele,
driverul de tastatură transmite sistemului de operare informaţiile legate de acţiunile asupra tastelor.
Windows salvează aceste acţiuni (sub formă de mesaje) în coada de aşteptare a sistemului. Mesajele de la
tastatură sunt apoi transferate, unul câte unul, în coada de mesaje a programului căruia îi aparţine fereastra
ce deţine „cursorul de intrare" (despre care vom discuta imediat). Programul distribuie mesajele procedurii
de fereastră corespunzătoare. Tastatura trebuie să fie partajată de toate aplicaţiile rulate simultan sub
Windows. Unele aplicaţii pot avea mai multe ferestre, iar tastatura trebuie să fie partajată de toate
ferestrele din cadrul aceleiaşi aplicaţii. Atunci când este apăsată o tastă, o singură fereastră trebuie să
primească mesajul privind apăsarea tastei respective. Fereastra care primeşte acest mesaj este fereastra
care deţine „cursorul de intrare" („input focus").

Raspunsuri la intrebari:
1. Ce se subînţelege sub noţiunea de “cursor de intrare”? Care sunt funcţiile lui?
Sub noţiunea “cursor de intrare” se subînţelege fereastra a carei este activă pentru primirea acţiunilor
din partea mousului, tastaturii sau a altui dispozitiv periferic. Funcţiile lui este de a indica dacă o
fereastră anumită primeşte sau pierde cursorul de intrare. În aşa mod dacă o fereastră deţine “cursorul
de intrare”, toate acţiunile îndeplinite de pe tastatură vor fi scrise în coada de aşteptare a ferestrei date.

2. Ce valori conţin parametrii lParam şi wParam în timpul prelucrării mesajelor parvenite de la


tastatură?
În timpul prelucrării mesajelor parvenite de la tastatură, parametrul lParam(pe 32 de biţi), transmisă
procedurii de fereastră este împărţită în şase cîmpuri: contorul de repetare, codul de scanare OEM,
indicatorul flag pentru taste extinse, codul de context, starea anterioară a tastei şi starea de tranziţie.
Parametrul wParam conţine codul virtual care identifică tasta apăsată sau eliberată.

3. Ce reprezintă codul de scanare OEM?


Codul de scanare OEM (OEM Scan Code) este codul de scanare al tastaturii, generat de
componentele hardware. În general, aplicaţiile Windows ignorează acest cod, deoarece există metode
mai bune de decodificare a informaţiilor de la tastatură.
4. Cum se obţine starea unei taste?

2
Pentru a obţine starea oarecărei taste, folosim funcţia GetKeyState, această funcţie este folosită, de
obicei, pentru obţinerea stării tastelor de modificare (Shift, Alt şi Ctrl) şi a tastelor de comutare (Caps
Lock, Num Lock¸ şi Scroll Lock).

5. Cum se verifică dacă mouse-ul este instalat şi câte butoane are?


Putem să determinăm dacă mouse-ul este prezent folosind funcţia GetSystemMetrics:
fMouse = GetSystemMetrics(SM_MOUSEPRESENT); Variabila fMouse va avea valoarea TRUE
(diferită de zero) dacă mouse-ul este instalat. Pentru determinarea numărului de butoane ale mouse-
ului instalat, folosiţi funcţia GetSystemMetrics:
cButtons = GetSystemMetrics(SM_CMOUSEBUTTONS);
Această funcţie returnează valoarea 0 dacă mouse-ul nu este instalat.

6. Unde se specifică indicatorul predefinit al mouse-lui?


Indicatorul predefinit al unei ferestre este specificat la definirea structurii clasei de ferestre. De
exemplu: wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
7. Ce valori conţin parametrii lParam şi wParam în timpul prelucrării mesajelor parvenite de la
mouse-ul?
Pentru toate mesajele, parametrul lParam conţine poziţia mouse-ului. Cuvîntul mai puţin semnificativ
conţine coordonata pe axa z, relative la colţul din stînga-sus al zonei client a ferestrei. Puteţi să
extrageţi coordonatele pe axele x şi z din parametrul lParam folosind macroinstrucţiunile LOWORD şi
HIWORD, definite în fişierele antet din Windows. Valoarea parametrului wParam indică starea
butoanelor mouse-ului şi starea tastelor Shift şi Ctrl.

8. În ce cazuri procedura de fereastră prelucrează mesajele generate de dublu-clic, efectuat pe


butonul mouse-ului?
Dacă vrem ca procedura de fereastră să primească mesajele generate de dublu-clic, trebuie să includeţi
identificatorul CS_DBLCLKS în stilul ferestrei, atunci cînd definiţi structura clasei de ferestre,
înaintea apelării funcţiei RegisterClassEx: Wndclass.style = CS_HREDRAW | CS_VREDRAW |
CS_DBCLKS Dacă în stilul ferestrei nu este inclus identificatorul CS_DBCLKS şi utilizatorul execută
d două ori clic pe butonul din stînga al mouse-ului într-o succesiune rapidă, procedura de fereastră va
recepţiona următoarele mesaje: WM_LBUTTONDOWN, WM_LBUTTONUP,
WM_LBUTTONDOWN şi WM_LBUTTONUP.

Listingul programului
3
#include <string.h>
#include <objidl.h>
#include <gdiplus.h>
#include <windows.h>
#include <stdlib.h>
#include <math.h>
#pragma comment (lib, "Gdiplus.lib")
using namespace Gdiplus;
LRESULT CALLBACK WndProc(HWND, UINT, WPARAM, LPARAM);
struct { int x, y; }
pos = { 900,100 };
struct{float x, y;}
stretch = { 1 };
struct{int x;}
rotate = { 0 };
int x, y, z = 0;
POINT pt[4];
HPEN hNewPen;
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR szCmdLine, int
iCmdShow) {
static TCHAR szAppName[] = TEXT("Window");
HWND hwnd;
MSG msg;
WNDCLASSEX wndclass;
GdiplusStartupInput gdiplusStartupInput;
ULONG_PTR gdiplusToken;
GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
// #Inregistrarea clasei ferestrei
wndclass.cbSize = sizeof(wndclass); //cbSize reprezinta dimensiunea structurii
wndclass.style = CS_HREDRAW | CS_VREDRAW;//se restabileste de fiecare data cand
fereastra este redimensionata, fie pe orizontala sau pe verticala
wndclass.lpfnWndProc = WndProc;
wndclass.cbClsExtra = 0;
wndclass.cbWndExtra = 0;
wndclass.hInstance = hInstance;
wndclass.hIcon = LoadIcon(NULL, IDI_INFORMATION);
wndclass.hCursor = LoadCursor(NULL, IDC_ARROW);
wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); //GetStockObject
obtine un obiect grafic (in acest caz o pensula folosita pentru desenarea fondului
ferestrei)
wndclass.lpszMenuName = NULL;
wndclass.lpszClassName = szAppName;
wndclass.hIconSm = LoadIcon(NULL, IDI_INFORMATION);
if (!RegisterClassEx(&wndclass)) { //inregistreaza o clasa de fereastra pentru
fereastra programului
MessageBox(NULL, TEXT("Inregistrarea ferestrei a esuat!"), TEXT("Eroare!"),
MB_ICONEXCLAMATION | MB_OK);
return 0;
}
// #Crearea ferestrei
hwnd = CreateWindow(szAppName, // numele clasei de fereastra (creaza o
fereastra pe baza unei clase de fereastra )
TEXT("Laborator"), // titlul ferestrei
WS_TILEDWINDOW, // stilul ferestrei
CW_USEDEFAULT, // pozitia initiala pe axa x
CW_USEDEFAULT, // pozitia initiala pe axa y
1366, // dimensiunea initiala pe axa x
760, // dimensiunea initiala pe axa y
NULL, // variabila handle a ferestrei parinte
NULL, // variabila handle a meniului
hInstance, // variabila handle a instantei programului
NULL); // parametri de creare
ShowWindow(hwnd, SW_MAXIMIZE);
UpdateWindow(hwnd);
// #Bucla de mesaje
while (GetMessage(&msg, NULL, 0, 0)) {
4
TranslateMessage(&msg);
DispatchMessage(&msg);
}
GdiplusShutdown(gdiplusToken);
return msg.wParam;
}
LRESULT CALLBACK WndProc(HWND hwnd, UINT iMsg, WPARAM wParam, LPARAM lParam) {
HDC hdc, hCompatibleDC;
PAINTSTRUCT ps;
RECT rect;
HANDLE hOldBitmap;
HANDLE hBitmap;
BITMAP Bitmap;
HBRUSH hBrush;
static POINT apt[4];
switch (iMsg) {
case WM_SIZE:
apt[0].x = 90;
apt[0].y = 90;
apt[1].x = 180;
apt[1].y = 200;
apt[2].x = 250;
apt[2].y = 50;
apt[3].x = 490;
apt[3].y = 150;
pt[0].x = 90;
pt[0].y = 375;
pt[1].x = 180;
pt[1].y = 475;
pt[2].x = 250;
pt[2].y = 325;
pt[3].x = 490;
pt[3].y = 435;
return 0;
case WM_PAINT: {
pos.x = pos.x > 1220 ? 1220 : pos.x;
pos.y = pos.y > 560 ? 560 : pos.y;
pos.x = pos.x < 862 ? 862 : pos.x;
pos.y = pos.y < 145? 145 : pos.y;
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd, &rect);
TextOut(hdc, 0, 0, TEXT("Tastele de control: Bezier-mouse left click;
Imagine-mouse right click"), 71);
TextOut(hdc, 0, 15, TEXT("Miscare imagine-
Up(sus),Right(dreapta),Down(jos),Left(stinga)"), 61);
TextOut(hdc, 0, 30, TEXT("Rotire imagine-PgUP,PgDown"), 26);
MoveToEx(hdc, 715, 0, NULL);// punctul initial (x,y)
LineTo(hdc, 715, 760); // punctul final (x,y)
MoveToEx(hdc, 0, 370, NULL);
LineTo(hdc, 715, 370);
PolyBezier(hdc, apt, 4);
SelectObject(hdc, hNewPen);
MoveToEx(hdc, pt[0].x, pt[0].y + 190, NULL);
for (float t = 0; t < 1; t += 0.01)
{
x = pow((1 - t), 3)*pt[0].x + 3 * t*pow((1 - t), 2)*pt[1].x + 3 *
t*t*(1 - t)*pt[2].x + t*t*t*pt[3].x;
y = pow((1 - t), 3)*pt[0].y + 3 * t*pow((1 - t), 2)*pt[1].y + 3 *
t*t*(1 - t)*pt[2].y + t*t*t*pt[3].y - 130;
LineTo(hdc, x, y + 320);
}
hBitmap = (HBITMAP)LoadImage(NULL, TEXT("image.bmp"), IMAGE_BITMAP, 0, 0,
LR_LOADFROMFILE);
Graphics graphics(hdc);
ImageAttributes IAttr;
RectF destination(25, 80, rect.right, rect.bottom);
Image image(L"image.bmp");
5
graphics.TranslateTransform(pos.x , pos.y);
graphics.RotateTransform(rotate.x);
graphics.TranslateTransform(-150, -150);
graphics.ScaleTransform(stretch.x, stretch.y);
graphics.DrawImage(&image, destination, 0, 0, 1400, 700, UnitPixel,
&IAttr);
EndPaint(hwnd, &ps);
break;
}
case WM_KEYDOWN:
switch (wParam){
case VK_RIGHT:
if (pos.x < 1220) {
pos.x+=5;
InvalidateRect(hwnd, NULL, TRUE);
}
break;
case VK_LEFT:
if (pos.x > 862) {
pos.x-=5;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
break;
case VK_UP:
if (pos.y > 145) {
pos.y-=5;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
break;
case VK_DOWN:
if (pos.y < 560) {
pos.y+=5;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
break;
case 0x21:
rotate.x--;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
case 0x22:
rotate.x++;
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
break;
}
break;
case WM_MOUSEMOVE:
/*z++;
if (z != 0 && z % 10 != 0) {
break;
}*/
if (wParam & MK_LBUTTON || wParam & MK_RBUTTON) {
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(BLACK_PEN));
PolyBezier(hdc, apt, 4);
if (wParam & MK_LBUTTON) {
apt[1].x = LOWORD(lParam);
apt[1].y = HIWORD(lParam);
InvalidateRect(hwnd, NULL, TRUE);
UpdateWindow(hwnd);
}
if (wParam & MK_RBUTTON) {
pos.x = LOWORD(lParam);
6
pos.y = HIWORD(lParam);
InvalidateRect(hwnd, NULL,TRUE);
UpdateWindow(hwnd);
}
SelectObject(hdc, GetStockObject(BLACK_PEN));
PolyBezier(hdc, apt, 4);
}
break;
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, iMsg, wParam, lParam);
}

Rezultatele obtinute

Concluzii

În urma executării acestei lucrări de laborator am studiat primitivele ce permit afișarea curbelor
Bezier cît cu ajutorul formulei predefinite atît și cu utilizarea formulelor matematice. Pentru
realizarea sarcinii propuse am creat un program ce generează două curbe Bezier și le afișează pe
ecran. Am studiat metodele și principiile de lucru cu tastatura și am însușit modul de prelucrare a
mesajelor provenite de la tastatură pentru a realiza sarcina propusă am creat un program simplu
care afișează o figură geometrică ce poate fi mișcată sau rotită cu ajutorul tastelor. Si am sușit
modul de prelucrare a mesajelor provenite de la mouse. Pentru a realiza sarcina propusă am creat
un program interactiv ce generează o fereastră cu un desen ce poate fi mișcat cît cu tastele atît și
cu ajutorul mișcării mouse-ului.

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