МIНIСТЕРСТВО ОСВIТИ І НАУКИ УКРАЇНИ
Національний унiверситет "Львiвська полiтехнiка"
ЗВІТ
до лабораторної роботи N 3
з курсу "Геометричне моделювання у конструюванні інженерних об'єктів і систем"
ГРАФІЧНІ ФУНКЦІЇ WINDOWS-ІНТЕРФЕЙСА (WinAPI) ЗАСОБАМИ BORLAND PASCAL 7.0 FOR WINDOWS ТА BORLAND DELPHI
Львiв 2005
МЕТА РОБОТИ
Мета роботи - ознайомлення та практичне освоєння технології й основ роботи з графічними можливостями Windows-інтерфейсу (WinAPI) операційного середовища Windows, що можуть викликатися прикладними програмами. Вивчити основні графічні функцій та процедури WinAPI (Win32API) засобами програмного середовища Borland Pascal 7.0 for Windows та візуального середовища програмування Borland Delphi, набути практичних навиків переходу з програмування графіки для операційної системи DOS до оволодіння принципами створення Windows-программ, розробки графічних процедур та програм WinAPI.
ТЕОРЕТИЧНІ ВІДОМОСТІ
DOS є однозадачной операційною системою. Програма, що виконується в середовищі DOS, керується потоком даних. Після ініціалізації (запуску програми) перша програмна процедура виробляє дані, і в залежності від їхнього змісту виробляється виконання наступної процедури, що знову генерує дані і так далі (рис. 3). При визначених даних виробляється деініціалізація програми.
Windows є багатозадачною операційною системою і по суті не може керуватися потоком даних. Після ініціалізації (запуску) програми керування одержує не яка-небудь робоча процедура цієї програми, а диспетчер подій.
Подія в термінах Windows розуміється як факт здійснення елементарної дії, від якого може залежати хід виконання програми. Це, приміром, натискання клавіші, переміщення курсору миші, завершення визначеного часового інтервалу.
Дії, виконувані диспетчером подій:
а) одержання (фіксація) події;
б) перевірка умови виходу з програми;
в) вибір потрібної процедури обробки події (диспетчирування).
Коли обрана процедура завершує роботу, керування знову повертається диспетчеру подій (рис. 4). При фіксації події, що завершує програму, диспетчер завершує свою роботу і передає керування процедурі деініціалізації.
WINDOWS API: СКЛАД І НАЙМЕНУВАННЯ
Терміном API (Application Programming Interface) називають інтерфейс прикладної програми Windows. Це повний набір процедур і функцій операційного середовища Windows, що можуть викликатися прикладними програмами під час їхньої роботи. У Borland Pascal ці процедури і функції представлені в TPW-модулях. Найбільше використовується з цих модулів модуль WinTypes (визначення констант і типів даних) та WinProcs (стандартні процедури і функції Windows).
Windows API включає близько 1000 функцій, і для полегшення орієнтування в них прийнято дотримувати так називаної угорської нотації - угоди про принципи іменування функцій, змінних і констант у Windows. Процедури і функції іменуються в стилі "дієслово-іменник", наприклад CreateWindow, SendMessage, TextOut (на відміну від OutText у DOS). Імена змінних і констант повинні містити префікс по типі чи даних способу використання. Для констант префікс визначає групу приналежності та відокремлюється нижнім підкресленням.
3. ІНДИВІДУАЛЬНЕ ЗАВДАННЯ
№6. Написати програму із застосуванням графічних функцій WinAPI, яка дозволяє
візуалізувати графік(и) функції з можливостями масштабування у вікні на певному інтервалі. Застосувати функції зміни кольору, штриховки, зафарбування замкнутих областей, текстових підписів, виводу координатної сітки. Організувати вивід графіка у зовнішній метафайл.
Побудувати графіки функції, заданої в параметричній формі, в одній області вікна для різних значень коефіцієнта "А".
Побудувати в різних областях екрана три графіки однієї функцій, заданої в полярних координатах р =р (ф) для різних значень коефіцієнтів А і В (р - полярний радіус, ф -кут у радіанах). Розу: р= А +sin(Вф); ф =[0. .10] ; А=[0 1]; В=[цілі та дробові]
ТЕКСТ ПРОГРАМИ
program Bagrij;
uses
SysUtils,
Windows,
Messages;
var
wc : TWndClassEx; // Зміна шаблону класу вікна.
MainWnd : HWND; // Описувач головного вікна.
Mesg : TMsg; // Змінна для циклу збора повідомлень.
xPos, yPos, nWidth, nHeight : Integer;
MyDC, WMFDC, OldDC : HDC; // Контекст пристрою.
zoom : Integer; // Масштаб (по замовчуванню 100).
brush : HBrush;
// Координати початків координат для всіх графіків.
ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, ox5, oy5, ox6, oy6 : integer;
MFile : HMetaFile; // Дескриптор метафайлу.
count : integer; // Допоміжна змінна.
rec : TRect; // Область вікна для малювання.
prec : PRect; // Область для метафайлу.
// Віконна процедура головного вікна.
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;
//---------------------------------------------------------------------------
// Процедура побудови графіка функції, з використанням ліній.
procedure DrawGraphicWithLines(ox, oy, zoom : integer; A,B, krok : double; color : longint);
var
x, y : integer;
ro, fi : double;
pen : HPen;
begin
pen := CreatePen(ps_Solid, 2, color);
SelectObject(MyDC, pen);
fi := 0.5;
ro := A+ sin(fi*B);
x := Round(ro*cos(fi)*zoom) + ox;
y := Round(ro*sin(fi)*zoom) + oy;
MoveToEx(MyDC, x, y, nil);
repeat
ro := A+ sin(fi*B);
x := Round(ro*cos(fi)*zoom) + ox;
y := Round(ro*sin(fi)*zoom) + oy;
LineTo(MyDC, x, y);
fi := fi + krok;
until fi > 12;
DeleteObject(pen);
end;
//---------------------------------------------------------------------------
// Процедура побудови координатних осей.
procedure DrawOsi(ox, oy, zoom : integer);
Var
pen : HPen;
brush : HBrush;
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, ox - zoom - 30, oy, nil);
LineTo(MyDC, ox + zoom + 30, oy); // Малюємо OX.
MoveToEx(MyDC, ox, oy + zoom + 30, nil);
LineTo(MyDC, ox, oy - zoom - 30); // Малюємо OY.
// 4. Малюємо стрілку для осі OX.
point[1].X := ox + zoom + 33;
point[1].Y := oy - 1;
point[2].X := ox + zoom + 13;
point[2].Y := oy + 4;
point[3].X := ox + zoom + 23;
point[3].Y := oy - 1;
point[4].X := ox + zoom + 13;
point[4].Y := oy - 5;
point[5].X := ox + zoom + 33;
point[5].Y := oy - 1;
Polygon(MyDC, point, 4);
// 5. Малюємо стрілку для осі OY.
point[1].X := ox - 1;
point[1].Y := oy - zoom - 33;
point[2].X := ox - 5;
point[2].Y := oy - zoom - 13;
point[3].X := ox;
point[3].Y := oy - zoom - 23;
point[4].X := ox + 4;
point[4].Y := oy - zoom - 13;
point[5].X := ox - 1;
point[5].Y := oy - zoom - 33;
Polygon(MyDC, point, 4);
// 6. Виводимо назви осей.
TextOut(MyDc, ox + zoom + 30, oy + 4, 'X', 1);
TextOut(MyDc, ox + 4, oy - zoom - 40, 'Y', 1);
// 7. Знищуємо об'єкти.
DeleteObject(brush);
DeleteObject(pen);
end;
//---------------------------------------------------------------------------
// Процедура побудови координатної сітки.
procedure DrawGrid(ox, oy, zoom : integer);
Var
pen : HPen;
x, y, krok : integer;
begin
pen := CreatePen(ps_Dot, 1, RGB(0, 0, 0));
SelectObject(MyDC, pen);
SetBkMode(MyDc, 1); // Робимо прозорий фон.
krok := 50;
y := oy + krok;
while y <= oy + zoom + 30 do
begin
MoveToEx(MyDC, ox - zoom - 30, y, nil);
LineTo(MyDC, ox + zoom + 30, y);
y := y + krok;
end;
y := oy - krok;
while y >= oy - zoom - 30 do
begin
MoveToEx(MyDC, ox - zoom - 30, y, nil);
LineTo(MyDC, ox + zoom + 30, y);
y := y - krok;
end;
x := ox - krok;
while x >= ox - zoom - 30 do
begin
MoveToEx(MyDC, x, oy + zoom + 30, nil);
LineTo(MyDC, x, oy - zoom - 30);
x := x - krok;
end;
x := ox + krok;
while x <= ox + zoom + 30 do
begin
MoveToEx(MyDC, x, oy + zoom + 30, nil);
LineTo(MyDC, x, oy - zoom - 30);
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.
' №29 ', // Заголовок вікна.
ws_overlappedwindow,// Прапорці стилів вікна.
xPos, // Горизонтальна позиція вікна.
yPos, // Вертикальна позиція вікна.
nWidth, // Ширина вікна.
nHeight, // Висота вікна.
0, // Описувач батьківського вікна (parent) чи вікна-володаря (owner).
0, // Описувач меню вікна (меню нема, нема і описувача).
Hinstance, // Описувач програми (application).
nil); // Address of window-creation data.
ShowWindow(MainWnd, CmdShow); // Відображуємо вікно.
// Задання початкових значень.
count := 0;
zoom := 50;
ox1 := 250;
oy1 := 170;
ox2 := 700;
oy2 := 170;
ox4 := 250;
oy4 := 520;
ox5 := 700;
oy5 := 520;
GetClientRect(MainWnd, rec);
new(prec);
prec.Left := rec.Left;
prec.Top := rec.Top;
prec.Right := rec.Right;
prec.Bottom := rec.Bottom;
// Цикл обробки повідомлень. Він може трохи видозмінюватися, але цей код присутній завжни.
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
if (count = 0) or (count >= 2) then
begin
Rectangle(MyDC, xPos, yPos, nWidth, nHeight);
// 1. Натиснення '+'.
if (Mesg.message = 256) and (Mesg.wParam = 107) then
begin
Rectangle(MyDC, xPos, yPos, nWidth, nHeight);
zoom := zoom + 20;
ox2 := ox2 + (zoom - 100)*2;
ox3 := ox3 + (zoom - 100)*4;
oy4 := oy4 + (zoom - 100)*2;
ox5 := ox5 + (zoom - 100)*2;
oy5 := oy5 + (zoom - 100)*2;
ox6 := ox6 + (zoom - 100)*4;
oy6 := oy6 + (zoom - 100)*2;
end
else if (Mesg.message = 256) and (Mesg.wParam = 109) then
begin
Rectangle(MyDC, xPos, yPos, nWidth, nHeight);
if zoom >= 100 then
begin
ox2 := ox2 - (zoom - 100)*2;
ox3 := ox3 - (zoom - 100)*4;
oy4 := oy4 - (zoom - 100)*2;
ox5 := ox5 - (zoom - 100)*2;
oy5 := oy5 - (zoom - 100)*2;
ox6 := ox6 - (zoom - 100)*4;
oy6 := oy6 - (zoom - 100)*2;
end;
zoom := zoom - 20;
end
else if (Mesg.message = 256) and (Mesg.wParam = 37) then
begin
ox1 := ox1 - 80;
ox2 := ox2 - 80;
ox3 := ox3 - 80;
ox4 := ox4 - 80;
ox5 := ox5 - 80;
ox6 := ox6 - 80;
end
else if (Mesg.message = 256) and (Mesg.wParam = 39) then
begin
ox1 := ox1 + 80;
ox2 := ox2 + 80;
ox3 := ox3 + 80;
ox4 := ox4 + 80;
ox5 := ox5 + 80;
ox6 := ox6 + 80;
end
else if (Mesg.message = 256) and (Mesg.wParam = 38) then
begin
oy1 := oy1 - 80;
oy2 := oy2 - 80;
oy3 := oy3 - 80;
oy4 := oy4 - 80;
oy5 := oy5 - 80;
oy6 := oy6 - 80;
end
else if (Mesg.message = 256) and (Mesg.wParam = 40) then
begin
oy1 := oy1 + 80;
oy2 := oy2 + 80;
oy3 := oy3 + 80;
oy4 := oy4 + 80;
oy5 := oy5 + 80;
oy6 := oy6 + 80;
end
else if (Mesg.message = 256) and (Mesg.wParam = 112) then
begin
end
else if (Mesg.message = 256) and (Mesg.wParam = 113) then
begin
end;
// 1. Малюємо перший графік.
DrawOsi(ox1+zoom-100, oy1+zoom-100, zoom);
DrawGrid(ox1+zoom-100, oy1+zoom-100, zoom);
DrawGraphicWithLines(ox1+zoom-100, oy1+zoom-100, zoom, -1,-2, 0.1, RGB(0, 168, 0));
TextOut(MyDc, ox1+zoom-100 - zoom - 20, oy1 + zoom+zoom-100 + 50, 'Рис. 1. Значення (A = -1; B = -2).', 34);
// 2. Малюємо другий графік.
DrawOsi(ox2+zoom-100, oy2+zoom-100, zoom);
DrawGrid(ox2+zoom-100, oy2+zoom-100, zoom);
DrawGraphicWithLines(ox2+zoom-100, oy2+zoom-100, zoom, 1,-2, 0.01, RGB(255, 168, 0));
TextOut(MyDc, ox2+zoom-100 - zoom - 20, oy2+zoom-100 + zoom + 50, 'Рис. 2. Значення (A = 1; B = -2).', 33);
// 3. Малюємо третій графік.
DrawOsi(ox4+zoom-100, oy4+zoom-100, zoom);
DrawGrid(ox4+zoom-100, oy4+zoom-100, zoom);
DrawGraphicWithLines(ox4+zoom-100, oy4+zoom-100, zoom, -1,0, 0.01, RGB(0, 168, 255));
TextOut(MyDc, ox4+zoom-100 - zoom - 20, oy4 + zoom+zoom-100 + 50, 'Рис. 3. Значення (A = -1; B = 0).', 33);
// 4. Малюємо перший графік.
DrawOsi(ox5+zoom-100, oy5+zoom-100, zoom);
DrawGrid(ox5+zoom-100, oy5+zoom-100, zoom);
DrawGraphicWithLines(ox5+zoom-100, oy5+zoom-100, zoom, 1,0, 0.01, RGB(255, 0, 0));
TextOut(MyDc, ox5+zoom-100 - zoom - 20, oy5+zoom-100 + zoom + 50, 'Рис. 4. Значення (A = 1; B = 0).', 32);
end;
end;
count := count + 1;
// ***********************************************************************
ReleaseDC(MainWnd,OldDC); // Звільнення зсилки.
DeleteDC(MyDC); // Видалення зсилки.
end;
end.
РЕЗУЛЬТАТ ВИКОНАННЯ ПРОГРАМИ
ВИСНОВОК
Програмування під операційну систему Windows є досить просте і дає великі можливості, хоча й потребує великих знань про принципи виконання програм та виникнення подій в системі.