Documente Academic
Documente Profesional
Documente Cultură
RAPORT
Lucrarea de laborator nr.3,4,5
Programarea in Windows
A efectuat:
A verificat:
lect., univ. Lisnic Inga
Chisinau 2017
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
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).
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.