Міністерство освіти та науки України
Національний університет “Львівська політехніка”
Кафедра САП
ЛАБОРАТОРНА РОБОТА №3
з курсу: “Геометричне моделювання у конструюванні інженерних об’єктів і систем”
ГРАФІЧНІ ФУНКЦІЇ WINDOWS-ІНТЕРФЕЙСУ (WinAPI) ЗАСОБАМИ BORLAND PASCAL 7.0 FOR WINDOWS ТА BORLAND DELPHI
МЕТА РОБОТИ
ТЕОРЕТИЧНІ ВІДОМОСТІ
3. ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
ТЕКСТ ПРОГРАМИ
program Plechin3;
uses
SysUtils,
Windows,
Messages;
var
wc : TWndClassEx; // Зміна шаблону класу вікна.
MainWnd : HWND; // Описувач головного вікна.
Mesg : TMsg; // Змінна для циклу збора повідомлень.
xPos, yPos, nWidth, nHeight : Integer; // Деякі параметри вікна.
MyDC, OldDC : HDC; // Контекст пристрою.
brush : HBrush; // Пензлик.
// Координати початків координат для всіх графіків.
ox1, oy1, ox2, oy2, ox3, oy3 : real;
// Зміщення центрів координат від центру екрана.
d_ox1, d_oy1, d_ox2, d_oy2, d_ox3, d_oy3 : real;
OX, OY : real; // Центр екрану.
rec : TRect; // Область вікна для малювання.
lenght, c_lenght : real; // Довжина півосі з її поч. незмінним значенням.
zoom : real; // Масштаб. По замовчуванню = 1.
// Віконна процедура головного вікна.
function WindowProc(wnd : HWND; Msg : Integer; Wparam : Wparam; Lparam : Lparam) : Lresult;
stdcall;
Begin
// Далі проходить цикл обробки повідомлень.
case msg of
wm_destroy :
// Повідомленні, яке надсилається при знищенні вікна.
begin
postquitmessage(0);
exit;
Result := 0;
end
else Result := DefWindowProc(wnd, msg, wparam, lparam);
end;
end;
//---------------------------------------------------------------------------
// Процедура побудови графіка функції y(x).
// Значення x і y множаться на 50 щоб більшим був графік.
procedure Yx(ox, oy, xbegin, xend, krok : real; color : longint);
var
x, y : double; // Центр графіка.
pen : HPen; // Тимчасове перо.
begin
pen := CreatePen(ps_Solid, 2, color); // Створюємо перо.
SelectObject(MyDC, pen); // Реєструємо його в контексті пристрою.
// Знаходимо першу точку графіка.
x := xbegin;
y := sin(x);
MoveToEx(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom), nil); // Переводимо туди курсор.
x := x + krok; // Збільшуємо кут.
// Знаходимо наступні точки графіка і малюємо лінії.
repeat
y := sin(x);
LineTo(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom));
x := x + krok;
until x > xend;
DeleteObject(pen); // Видаляєм перо.
end;
//---------------------------------------------------------------------------
// Процедура побудови графіка функції y3(x).
// Значення x і y множаться на 50 щоб більшим був графік.
procedure Y3x(ox, oy, xbegin, xend, krok : real; color : longint);
var
x, y, m : double; // Центр графіка.
pen : HPen; // Тимчасове перо.
begin
pen := CreatePen(ps_Solid, 2, color); // Створюємо перо.
SelectObject(MyDC, pen); // Реєструємо його в контексті пристрою.
// Знаходимо першу точку графіка.
x := xbegin;
y := x - x*x*x/6 + x*x*x*x*x/120;
MoveToEx(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom), nil); // Переводимо туди курсор.
x := x + krok; // Збільшуємо кут.
// Знаходимо наступні точки графіка і малюємо лінії.
repeat
y := x - x*x*x/6 + x*x*x*x*x/120;
LineTo(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom));
x := x + krok;
until x > xend;
DeleteObject(pen); // Видаляєм перо.
end;
//---------------------------------------------------------------------------
// Процедура побудови графіка функції y4(x).
// Значення x і y множаться на 50 щоб більшим був графік.
procedure Y4x(ox, oy, xbegin, xend, krok : real; color : longint);
var
x, y, m : double; // Центр графіка.
pen : HPen; // Тимчасове перо.
begin
pen := CreatePen(ps_Solid, 2, color); // Створюємо перо.
SelectObject(MyDC, pen); // Реєструємо його в контексті пристрою.
// Знаходимо першу точку графіка.
x := xbegin;
y := x - x*x*x/6 + x*x*x*x*x/120 - x*x*x*x*x*x*x/5040;
MoveToEx(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom), nil); // Переводимо туди курсор.
x := x + krok; // Збільшуємо кут.
// Знаходимо наступні точки графіка і малюємо лінії.
repeat
y := x - x*x*x/6 + x*x*x*x*x/120 - x*x*x*x*x*x*x/5040;
LineTo(MyDC, Round(x*50*zoom+ox), Round(oy-y*50*zoom));
x := x + krok;
until x > xend;
DeleteObject(pen); // Видаляєм перо.
end;
//---------------------------------------------------------------------------
// Процедура побудови координатних осей.
procedure DrawOsi(ox, oy : real);
Var
pen : HPen; // Тимчасове перо.
brush : HBrush; // Тимчасовий пензль.
// Масим для функції Polygon(), яка малює стрілки для осьових ліній.
point : array [1..5] of TPoint;
begin
// 1. Створуємо перо і реєструємо його в контексті пристрою.
pen := CreatePen(ps_Solid, 2, RGB(0, 0, 0));
SelectObject(MyDC, pen);
// 2. Створюємо пензлик і реєструємо його в контексті пристрою.
brush := CreateSolidBrush(RGB(0, 0, 0));
SelectObject(MyDC, brush);
SetBkMode(MyDc, 1); // Робимо прозорий фон.
// 3. Малюємо осі координат.
MoveToEx(MyDC, Round(ox - lenght), Round(oy), nil);
LineTo(MyDC, Round(ox + lenght), Round(oy)); // Малюємо OX.
MoveToEx(MyDC, Round(ox), Round(oy + lenght), nil);
LineTo(MyDC, Round(ox), Round(oy - lenght)); // Малюємо OY.
// 4. Малюємо стрілку для осі OX.
point[1].X := Round(ox + lenght);
point[1].Y := Round(oy - 1);
point[2].X := Round(ox + (lenght - 13));
point[2].Y := Round(oy + 4);
point[3].X := Round(ox + (lenght - 5));
point[3].Y := Round(oy - 1);
point[4].X := Round(ox + (lenght - 13));
point[4].Y := Round(oy - 5);
point[5].X := Round(ox + lenght);
point[5].Y := Round(oy - 1);
Polygon(MyDC, point, 4);
// 5. Малюємо стрілку для осі OY.
point[1].X := Round(ox - 1);
point[1].Y := Round(oy - lenght);
point[2].X := Round(ox - 5);
point[2].Y := Round(oy - (lenght - 13));
point[3].X := Round(ox);
point[3].Y := Round(oy - (lenght - 5));
point[4].X := Round(ox + 4);
point[4].Y := Round(oy - (lenght - 13));
point[5].X := Round(ox - 1);
point[5].Y := Round(oy - lenght);
Polygon(MyDC, point, 4);
// 6. Виводимо назви осей.
TextOut(MyDc, Round(ox + lenght-12), Round(oy + 4), 'X', 1);
TextOut(MyDc, Round(ox + 4), Round(oy - lenght), 'Y', 1);
// 7. Знищуємо об'єкти.
DeleteObject(brush);
DeleteObject(pen);
end;
//---------------------------------------------------------------------------
// Процедура побудови координатної сітки.
procedure DrawGrid(ox, oy : real);
Var
pen : HPen; // Тимчасове перо.
x, y, krok : real;
begin
pen := CreatePen(ps_Dot, 1, RGB(0, 0, 0));// Створюємо перо.
SelectObject(MyDC, pen); // Реєструємо його в контексті пристрою.
SetBkMode(MyDc, 1); // Робимо прозорий фон.
krok := 40; // Відстань між лініями.
// 1. Малюємо лінії вниз від осі ОХ.
y := oy + krok;
while y <= oy + lenght do
begin
MoveToEx(MyDC, Round(ox - lenght), Round(y), nil);
LineTo(MyDC, Round(ox + lenght), Round(y));
y := y + krok;
end;
// 2. Малюємо лінії вгору від осі ОХ.
y := oy - krok;
while y >= oy - lenght do
begin
MoveToEx(MyDC, Round(ox - lenght), Round(y), nil);
LineTo(MyDC, Round(ox + lenght), Round(y));
y := y - krok;
end;
// 3. Малюємо лінії вліво від осі ОY.
x := ox - krok;
while x >= ox - lenght do
begin
MoveToEx(MyDC, Round(x), Round(oy + lenght), nil);
LineTo(MyDC, Round(x), Round(oy - lenght));
x := x - krok;
end;
// 4. Малюємо лінії вправо від осі ОY.
x := ox + krok;
while x <= ox + lenght do
begin
MoveToEx(MyDC, Round(x), Round(oy + lenght), nil);
LineTo(MyDC, Round(x), Round(oy - lenght));
x := x + krok;
end;
DeleteObject(pen); // Видаляєм перо.
end;
//---------------------------------------------------------------------------
begin
// Далі йде заповнення шаблону класу вікна.
wc.cbSize := sizeof(wc);
wc.style := cs_hredraw or cs_vredraw;
wc.lpfnWndProc := @WindowProc;
wc.cbClsExtra := 0;
wc.cbWndExtra := 0;
wc.hInstance := HInstance;
wc.hIcon := LoadIcon(0, idi_application);
wc.hCursor := LoadCursor(0, idc_arrow);
wc.hbrBackground := COLOR_BTNFACE + 1;
wc.lpszMenuName := nil;
wc.lpszClassName := 'WinMin: Main';
RegisterClassEx(wc); // Реєстрація нового класу в системі.
// Заповнення змінних xPos, yPos, nWidth, nHeight.
xPos := 0;
yPos := 0;
nWidth := 1024;
nHeight := 739;
// Створення головного вікна.
MainWnd := CreateWindowEx(0, // Прапорці розширених стилів.
'WinMin: Main', // Ім'я класу вікна, яке задане при заповненні структури wc.
'Виконала студентка групи КН-46 Плечінь Василмна.', // Заголовок вікна.
ws_overlappedwindow, // Прапорці стилів вікна.
xPos, // Горизонтальна позиція вікна.
yPos, // Вертикальна позиція вікна.
nWidth, // Ширина вікна.
nHeight, // Висота вікна.
0, // Описувач батьківського вікна (parent) чи вікна-володаря (owner).
0, // Описувач меню вікна (меню нема, нема і описувача).
Hinstance, // Описувач програми (application).
nil); // Address of window-creation data.
ShowWindow(MainWnd, CmdShow); // Відображуємо вікно.
// **************************** Мій власний код. ***************************
// 1. Знаходимо центр екрану.
OX := nWidth/2;
OY := nHeight/2;
// 2. Задаєм початковий масштаб.
zoom := 1;
// 3. Ініціалізація початкових координат центрів.
c_lenght := 160;
lenght := c_lenght;
ox1 := 190;
oy1 := 540;
ox2 := 507;
oy2 := 190;
ox3 := 830;
oy3 := 540;
// 4. Знаходження відхилень центрів графіків від центру екрана.
d_ox1 := ox1 - OX;
d_oy1 := oy1 - OY;
d_ox2 := ox2 - OX;
d_oy2 := oy2 - OY;
d_ox3 := ox3 - OX;
d_oy3 := oy3 - OY;
// **************************************************************************
GetClientRect(MainWnd, rec);
// Цикл обробки повідомлень. Він може трохи видозмінюватися, але цей код присутній завжни.
While GetMessage(Mesg,0,0,0) do
begin
TranslateMessage(Mesg);
DispatchMessage(Mesg);
// Робота з графічними функціями.
MyDC:=GetDC(MainWnd); // Отримання контексту пристрою виводу.
SaveDC(OldDC);
// ************************ Мій власний код. ***************************
// Графіки будуть перемальовуватись лише при натисненні клавіші або при двох
// подіях зв'язаних з перемалюванням вікна.
if (Mesg.message = 256) or (Mesg.message = 15) or (Mesg.message = 49366) then
begin
Rectangle(MyDC, xPos, yPos, nWidth, nHeight); // Все стираємо.
// 1. Натиснення '+' - збільшуємо графіки.
if (Mesg.message = 256) and (Mesg.wParam = 107) then
begin
zoom := zoom + 0.05;
lenght := c_lenght*zoom;
ox1 := OX + d_ox1*zoom;
oy1 := OY + d_oy1*zoom;
ox2 := OX + d_ox2*zoom;
oy2 := OY + d_oy2*zoom;
ox3 := OX + d_ox3*zoom;
oy3 := OY + d_oy3*zoom;
end
// 2. Натиснення '-' - зменшуємо графіки.
else if (Mesg.message = 256) and (Mesg.wParam = 109) and (zoom > 0.1) then
begin
zoom := zoom - 0.05;
lenght := c_lenght*zoom;
lenght := c_lenght*zoom;
ox1 := OX + d_ox1*zoom;
oy1 := OY + d_oy1*zoom;
ox2 := OX + d_ox2*zoom;
oy2 := OY + d_oy2*zoom;
ox3 := OX + d_ox3*zoom;
oy3 := OY + d_oy3*zoom;
end
// 3. Натиснення стрілки '<-' - посуваємо графіки вправо .
else if (Mesg.message = 256) and (Mesg.wParam = 39) then
begin
ox1 := ox1 - 80;
ox2 := ox2 - 80;
ox3 := ox3 - 80;
end
// 4. Натиснення стрілки '->' - посуваємо графіки вліво.
else if (Mesg.message = 256) and (Mesg.wParam = 37) then
begin
ox1 := ox1 + 80;
ox2 := ox2 + 80;
ox3 := ox3 + 80;
end
// 5. Натиснення стрілки 'вгору' - посуваємо графіки вниз .
else if (Mesg.message = 256) and (Mesg.wParam = 40) then
begin
oy1 := oy1 - 80;
oy2 := oy2 - 80;
oy3 := oy3 - 80;
end
// 6. Натиснення стрілки 'вниз' - посуваємо графіки вгору.
else if (Mesg.message = 256) and (Mesg.wParam = 38) then
begin
oy1 := oy1 + 80;
oy2 := oy2 + 80;
oy3 := oy3 + 80;
end;
// 1. Малюємо перший графік.
DrawOsi(ox1, oy1);
DrawGrid(ox1, oy1);
Yx(ox1, oy1, -3, 3, 0.01, RGB(205, 1, 27));
TextOut(MyDc, Round(ox1-lenght), Round(oy1-lenght-20), 'y = sin(x), [-3; 3].', 22);
// 2. Малюємо другий графік.
DrawOsi(ox2, oy2);
DrawGrid(ox2, oy2);
Y3x(ox2, oy2, -3, 3, 0.01, RGB(0, 168, 0));
TextOut(MyDc, Round(ox2-lenght), Round(oy2-lenght-20), 'y = x - x^3/3! + x^5/5!, [-3; 3].', 35);
// 3. Малюємо третій графік.
DrawOsi(ox3, oy3);
DrawGrid(ox3, oy3);
Y4x(ox3, oy3, -3, 3, 0.01, RGB(0, 0, 255));
TextOut(MyDc, Round(ox3-lenght), Round(oy3-lenght-20), 'y = x - x^3/3! + x^5/5! - x^7/7!, [-3; 3].', 44);
end;
// ***********************************************************************
ReleaseDC(MainWnd,OldDC); // Звільнення зсилки.
DeleteDC(MyDC); // Видалення зсилки.
end;
end.
РЕЗУЛЬТАТ ВИКОНАННЯ ПРОГРАМИ
ВИСНОВОК
Програмування під операційну систему Windows є досить просте і дає великі можливості, хоча й потребує великих знань про принципи виконання програм та виникнення подій в системі.