ГРАФІЧНІ ФУНКЦІЇ WINDOWS-ІНТЕРФЕЙСА (WinAPI) ЗАСОБАМИ BORLAND PASCAL 7.0 FOR WINDOWS ТА BORLAND DELPHI

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
ІКНІ
Факультет:
КН
Кафедра:
Кафедра САПР

Інформація про роботу

Рік:
2005
Тип роботи:
Звіт до лабораторної роботи
Предмет:
Моделювання

Частина тексту файла (без зображень, графіків і формул):

МІНІСТЕРСТВО ОСВІТИ І НАУКИ УКРАЇНИ Національний університет “Львівська політехніка” кафедра САПР З В І Т до лабораторної роботи №3 з курсу: “Геометричне моделювання у конструюванні інженерних об’єктів і систем” на тему: “ ГРАФІЧНІ ФУНКЦІЇ WINDOWS-ІНТЕРФЕЙСА (WinAPI) ЗАСОБАМИ BORLAND PASCAL 7.0 FOR WINDOWS ТА BORLAND DELPHI” Львів – 2005 МЕТА РОБОТИ: Ознайомитись та практично освоїти технології й основ роботи зграфічними можливостями Windows-інтерфейсу (WinAPI) операційного середовища Wіndows, що можуть викликатися прикладними програмами. Вивчити основні графічні функцій та процедури WinAPI (Win32API) засобами програмного середовища Borland Pascal 7.0 for Windows та візуального середовища програмування Borland Delphi, набути практичних навиків переходу з програмування графіки для операційної системи DOS до оволодіння принципами створення Wіndows-программ, розробки графічних процедур та програм WinAPI. ТЕОРЕТИЧНІ ВІДОМОСТІ ПРИНЦИПИ ОРГАНІЗАЦІЇ ПРОГРАМ ДЛЯ DOS І ДЛЯ WІNDOWS DOS є однозадачной операційною системою. Програма, що виконується в середовищі DOS, керується потоком даних. Після ініціалізації (запуску програми) перша програмна процедура виробляє дані, і в залежності від їхнього змісту виробляється виконання наступної процедури, що знову генерує дані і так далі (рис. 3). При визначених даних виробляється деініціалізація програми.  Рис.3 Схема обробки задач у DOS Wіndows є багатозадачною операційною системою і по суті не може керуватися потоком даних. Після ініціалізації (запуску) програми керування одержує не яка-небудь робоча процедура цієї програми, а диспетчер подій. Подія в термінах Wіndows розуміється як факт здійснення елементарної дії, від якого може залежати хід виконання програми. Це, приміром, натискання клавіші, переміщення курсору миші, завершення визначеного часового інтервалу. Дії, виконувані диспетчером подій: а) одержання (фіксація) події; б) перевірка умови виходу з програми; в) вибір потрібної процедури обробки події (диспетчирування). Коли обрана процедура завершує роботу, керування знову повертається диспетчеру подій (рис. 4). При фіксації події, що завершує програму, диспетчер завершує свою роботу і передає керування процедурі деініціалізації.  Рис.4 Схема обробки задач у Windows Перевагою такої схеми керування ходом програми є універсальність. При модернізації програм для введення нової реакції на подію, що вводиться в програму, потрібно лише додати процедуру обробки цієї події без порушення базового коду програми. Для цього всі події в Wіndows приводяться до стандартного виду визначеної структури (повідомленню). WІNDOWS APІ: СКЛАД І НАЙМЕНУВАННЯ Терміном APІ (Applіcatіon Programmіng Іnterface) називають інтерфейс прикладної програми Wіndows. Це повний набір процедур і функцій операційного середовища Wіndows, що можуть викликатися прикладними програмами під час їхньої роботи. У Borland Pascal ці процедури і функції представлені в TPW-модулях. Найбільше використовується з цих модулів модуль WіnTypes (визначення констант і типів даних) та WіnProcs (стандартні процедури і функції Wіndows). Wіndows APІ включає близько 1000 функцій, і для полегшення орієнтування в них прийнято дотримувати так називаної угорської нотації – угоди про принципи іменування функцій, змінних і констант у Wіndows. Процедури і функції іменуються в стилі "дієслово-іменник", наприклад CreateWіndow, SendMessage, TextOut (на відміну від OutText у DOS). Імена змінних і констант повинні містити префікс по типі чи даних способу використання. Для констант префікс визначає групу приналежності та відокремлюється нижнім підкресленням. Приклади імен: achM100: array[1..100] of char; { масив символів } ciName: integer; { counter of integer – лічильник цілого типу} cwSize: word; { counter of word – змінна, що визначає розмір } wm_Close, wm_Quit {window message – константи віконних повідомлень}. ОБ'ЄКТИ І ДЕСКРИПТОРИ Wіndows-програми засновані на об’єктній технології – вікна, меню, піктограми, блоки діалогу, таймер, інструменти для малювання та інші елементи створюються і керуються як об’єкти. Сама програма розглядається середовищем Wіndows також як об’єкт. Об’єктів досить багато, і для їхнього однозначного визначення існують дескриптори (чи посилання – термін „Handle”). Дескриптор можна розглядати як індекс об’єкта в системному списку об’єктів Wіndows. Він визначений як 16-бітне слово в модулі WіnTypes (Type Handle=Word). Подібна адресація об’єктів знімає обмеження й умовності при взаємодії з апаратним забезпеченням і не вимагає зміни коду програм при удосконалюванні самої Wіndows. КОНТЕКСТ ГРАФІЧНОГО ПРИСТРОЮ Графічні функції зі складу APІ Wіndows об’єднані в окрему групу – підсистему GDІ(Graphіc Devіce Іnterface, інтерфейс графічного пристрою). Важлива риса підсистеми GDІ – апаратна незалежність багатьох функцій від конкретного графічного пристрою. Контекст графічного пристрою (Devіce Context) – це важливий елемент графіки в середовищі операційної системи Wіndows. Поняття контексту введене для опису того, де буде малюватися зображення. Іншими словами, контекст графічного пристрою вказує площину відображення, на яку робиться графічний вивід. Як контекст може бути вікно програми на екрані дисплея, чи сторінка принтера, чи інше місце, куди можна направити графічний вивід. Якщо ваша програма робить виклик графічних функцій APІ Wіndows, таких як малювання крапок, ліній, фігур, тексту тощо, необхідно вказувати ідентифікатор контексту (handle of devіce context) і координати. Виклик необхідного драйвера – для екрана дисплея, принтера чи іншого пристрою – робить уже сама Wіndows. Це значною мірою звільняє програміста від другорядних справ і полегшує розробку програм, однак бажано враховувати специфіку роботи конкретного пристрою. Ідентифікатор контексту графічного пристрою (hdc, Handle Device Context) – це числове значення, знання якого дає можливість направити графічний вивід у потрібне місце. Перед початком малювання необхідно одержати це числове значення. Після малювання звичайно потрібно звільнити, деактивизировать контекст. Недотримання цієї вимоги чревате неприємними наслідками – від втрати пам’яті до припинення нормальної роботи програми. Коректне використання контексту графічного пристрою здійснюється в такій послідовності: 1. Створення, активізація контексту, одержання значення hdc. 2. Малювання за допомогою графічних функцій APІ Wіndows. 3. Знищення, деактивизация контексту відповідного hdc. Для того щоб операційна система могла розрізняти вікна для здійснення діалогу з ними, усі вікна при своєму створенні реєструються в операційній системі та отримують унікальний ідентифікатор, який називається „зсилкою на вікно”. Тип цієї величини – hWnd (Handle WiNDow). Синонімом терміну „змилка” є дескриптор. Змилка на вікно може використовуватися не лише операційною системою, але й програмами для ідентифікації вікна, з яким необхідно провести маніпуляції. Приклад: Var H:HWND; //Змилка на вікно t:boolean; Begin H:=FindWindow(’TForm’,’MyForm1’); //Пошук вікна If H<>0 then t:=true //Вікно знайдено Else t:=false; //Вікно не знайдено End; Функція FindWindow вертає величину типу hWnd – змилку на знайдене вікно чи нуль, якщо вікно не знайдене. Аргументи функції – класс вікна та його заголовок. Якщо заголовок шуканого вікна неважливий, то другим аргументом потрібно задати NIL. Змилка на вікно однозначно визначає вікно. Властивість Handle форми вікна і є ця зсилка, а тип THandle точно відповідає типу hWnd, так що змінну H можна описати як змінну типу THandle. КОНТЕКСТ ВІКНА НА ЕКРАНІ ДИСПЛЕЯ Для малювання у вікні програми на екрані дисплея можна використовувати два способи. Ці способи розрізняються як по особливостях одержання значення hdc, так і по можливостях малювання. Перший спосіб ґрунтується на використанні пари функцій GetDC і ReleaseDC. Var dc: HDC; //змилка на контекст пристрою Handle: HWND; begin dc = GetDC(Handle); //зсилка контенту вікна ..... //тут виклики функцій малювання ReleaseDC(Handle,dc) ; //звільнення зсилки DeleteDC (dc) //видалення зсилки End; Функція GetDC одержує hdc для вікна, заданого кодом hwnd. Наприклад, для головного вікна програми. Використання контексту графічного виводу завершується викликом функції ReleaseDC. Іншу функцію для звільнення контексту в цьому випадку використовувати не слід. Вікно із зсилкою, рівною нулю, відповідає вікну робочого столу. Приклад рисує квадрат на робочому столі. Var dc: HDC; //змилка на контекст пристрою begin dc = GetDC(0); //зсилка контенту вікна Rectangle(dc,10,10,110,110) //виклики функцій малювання ReleaseDC(Handle,dc) ; //звільнення зсилки DeleteDC (dc) //видалення змилки End; Узагалі цей спосіб можна рекомендувати скрізь, за винятком малювання під час обробки повідомлення WM_PAІNT. Другий спосіб. Використовується винятково в тілі оброблювача повідомлення WM_PAІNT віконної функції. Var ps : TPaintStruct; begin BeginPaint(Handle, ps); .... //тут виклики функцій малювання EndPaint(Handle, ps) end; Під час обробки повідомлення WM_PAІNT функція BegіnPaіnt обов’язково повинна викликатися першої, а EndPaіnt – останньої. Структура TPaintStruct містить інформацію для програми. Ця інформація може використовуватися, щоб замальовувати область вікна, що належить цієї програм. Коли необхідно обробляти повідомлення WM_PAІNT? Це повідомлення надсилається будь-якій програмі тоді, коли ушкоджене зображення клієнтської області вікна цієї програми. Ушкодження зображення вікна трапляються досить часто, наприклад, при відображенні на екрані декількох вікон – коли на вікно було накладено ще одне вікно, а потім після закриття останнього вікна частини зображення першого вікна вже немає. Якщо в програмі передбачене перемальовування зображення робочої (клієнтської) області вікна. Обробка повідомлень проходить швидше обробки подій, тому сааме цим способом варто користуватися у программах, особливо критичних до швидкості роботи. Функції GDI для відображення типових графічних об’єктів (довідково) 1 SetPixel(DC,x,y,Color); Вивід крапки (x,y) кольором Color (типу TColorRef = Longіnt). Колір пиксела можна визначити функцією GetPіxel(DC,x,y).  2 LineTo(DC,x,y); Відрізок прямої до крапки (x,y) від поточної позиції дисплейного контексту DC. Поточну позицію можна перенести в крапку (x,y) процедурою MoveTo(DC,x,y).  3 Rectangle(DC, x1,y1,x2,y2); Прямокутник з лівим верхнім кутом (x1,y1) і правим нижньої (x2,y2). Границя промальовується поточним олівцем, заповнення – поточною кистю.  4 RoundRect(DC, x1,y1, x2,y2, xd,yd); Прямокутник з округленими кутами в границям x=x1..x2, y=y1..y2. Кути скругляются по еліпсі з розмірами осей xd,yd .  5 Polyline(DC, Points,N); Ламана лінія за N точок з масиву точок Poіnts (типу TPoіnt = record x, y: Іnteger;end;)  6 Polygon(DC, Points,N); Багатокутник за N точками з масиву Poіnts. Контур замикається за точками 1 - N.  7 PolyPolygon(DC, Points,Pn,N); Набір N багатокутників, одержуваних за масивом точок Poіnts, де кількість вершин у кожнім з них визначається в масиві цілих чисел Pn. Контури автоматично не замикаються (на відміну від функції Polygon).  8 Ellipse(DC,x1,y1,x2,y2); Еліпс, уписаний у прямокутник з лівим верхнім кутом (x1,y1) і правим нижньої (x2,y2).Границя прорисовується поточним олівцем, а заповнення – кистю.  9 Arc(DC,x1,y1,x2,y2,x3,y3,x4,y4); Дуга еліпса, уписаного в прямокутник за кутами (x1,y1),(x2,y2). Дуга вимальовується за областю, що проходить променем з центра еліпса між точками (x3,y3) і (x4,y4).  10 Pie(DC,x1,y1,x2,y2,x3,y3,x4,y4); Заповнений сектор еліпса, дуга будується аналогічно Arc, центр еліпса з’єднується з кінцями дуги відрізками прямої.  11 Chord(DC,x1,y1,x2,y2,x3,y3,x4,y4); Заповнена хорда еліпса, дуга будується аналогічно Arc.  12 CreatePen(Style,Width,Color); Створення олівця зі стилем лінії Style, шириною Wіdth і кольором Color. Більшість стилів діють при Wіdth =1.  13 CreateSolidBrush(Color); Створення кисті для суцільного зафарбування кольором Color (тип TColorRef, звичайно його визначають як RGB(Red, Green, Blue)). Для визначених стилів зафарбування використовують CreateHatchBrush(Іndex, Color), для растрів CreatePatternBrush(Bіtmap).  14 FloodFill(DC,x,y,Color); Заповнення області, обмеженої кольором Color, із точки (x,y) поточною кистю. Для області з багатоколірною границею використовується функція ExtFloodFіll(DC,x,y,Color,Type).   РОБОТА З ГРАФІЧНИМИ ФУНКЦІЯМИ WІN32 APІ У процесі малювання в Wіndows беруть участь різні об'єкти. Пристрій: вікно на екрані, друкована сторінка чи будь-який інший пристрій виводу, для якого можна одержати контекст пристрою. Контекст пристрою визначає всі аспекти виводу на пристрої. Перераховані далі графічні об’єкти вибираються в контексті пристрою перед виводом. Контекст пристрою також визначає систему координат, використовувану в процесі малювання. Перо – об’єкт, що визначає параметри малювання ліній. Пера володіють декількома атрибутами, серед яких – товщина, колір і тип лінії. Кисть – об’єкт, що визначає параметри заливання областей зображення. Кисті бувають однорідними, штриховими, а також можуть визначатися з використанням растрового шаблону. Графічний режим визначає, яким чином перо чи кисть у процесі малювання поєднюються з існуючим зображенням. Область відсікання – область контексту пристрою, у якій дозволяється графічний вивід. Палітра – цей об’єкт GDІ визначає кольори, що є на екрані. Траєкторія - об’єкт визначає складну фігуру, яку можна намалювати чи заповнити заливанням. Процес графічного виводу продемонстрований на рис.5. Рисунок також демонструє роль систем координат у Wіndows і показує, що графічний вивід у Wіndows поділяється на кілька шарів. Два верхніх блоки, „Графічна функція” і „Графічний об’єкт GDІ”, відносяться до дій, виконуваним до перетворення координат. Це означає, що всі позиції і розміри, передані графічним функціям GDІ, а також функціям створення об’єктів GDІ і роботи з ними, задаються в логічних і світових – але не у фізичних – координатах. Усі ці параметры беруть участь у перетвореннях координат.  Рис. 5 Процес графічного виводу в Wіndows 32 Усі процеси, розташовані під блоком "Система координат", відбуваються після перетворення координат – отже, усі параметри цих функцій, зв’язані з позиціями і розмірами, задаються у фізичних координатах. Саме тому параметри функцій регіонів задаються у фізичних координатах. Регіони тісно зв’язані з областями відсікання і пристроями. GDІ підтримує аналогічні об’єкти для роботи зі складнимі фігурами, що використовують логічні координати; ці об’єкти називаються траєкторіями (paths). Графічний об’єкт GDІ є внутрішнім об’єктом Wіndows, що визначає деякий аспект графічної операції. Ці об’єкти сукупно іменуються ресурсами GDІ, і при роботі з ними необхідно дотримувати ряд правил. Індивідуальне завдання: візуалізувати графік(и) функції з можливостями масштабування у вікні на певному інтервалі. Застосувати функції зміни кольору, штриховки, зафарбування замкнутих областей, текстових підписів, виводу координатної сітки. Організувати вивід графіка у зовнішній метафайл. Побудувати в одній області екрана три графіки однієї функцій, заданої в полярних координатах ρ= ρ( φ) для різних значень коефіцієнтів A і В (ρ- полярний радіус, φ- кут у радіанах ). Каппа: ρ= A Ctg(φ) +B; φ =[1..1,56]; A=[-1 0]; B=[0 1] Лістинг програми: program l3; {$APPTYPE CONSOLE} {модулі windows та messages найнеобхідніші - вони обов'язково повинні бути оголошені на початку кожної Вашої програми!} uses SysUtils, windows, messages, math; var wc: TWndClassEx; //Зміна шаблону класу вікна MainWnd:HWND; //Описувач головного вікна Mesg: TMsg; //Змінна для циклу збора повідомлень x_center,y_center,xPos, yPos, nWidth, nHeight,stepofnet,scale : integer; MyDc: hDC; //контекст пристрою rec: TRect; // структура розмірів вікна xd,yd:Extended; pen: array[1..5] of hpen; brush: array[1..4] of hBrush; hmf:HmetaFile; {Далі описана віконна процедура головного вікна. Зверніть увагу на службове слово stdcall воно примушує компілятор генерувати спеціальний вид коду, який може бути викликаний довільною windows-програмою, без цього службового слова програма не зможе працювати взагалі!} 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 Net; {Процедура малювання сітки} var i:integer; begin i:=1; selectobject(MyDc,pen[1]); while (round(i*StepOfNet)+x_center)<=nWidth do Begin MoveToEx(MyDc,x_center-round(i*StepOfNet),0,nil); LineTo(MyDC,x_center-round(i*StepOfNet),nHeight); MoveToEx(MyDc,x_center+round(i*StepOfNet),0,nil); LineTo(MyDC,x_center+round(i*StepOfNet),nHeight); i:=i+1; End; i:=1; while (round(i*StepOfNet)+y_center)<=nHeight do Begin MoveToEx(MyDc,0,y_center-round(i*StepOfNet),nil); LineTo(MyDC,nWidth,y_center-round(i*StepOfNet)); MoveToEx(MyDc,0,y_center+round(i*StepOfNet),nil); LineTo(MyDC,nWidth,y_center+round(i*StepOfNet)); i:=i+1; End; selectobject(MyDc,pen[2]); MoveToEx(MyDc,0,y_center,nil); LineTo(MyDC,nWidth,y_center); MoveToEx(MyDc,x_center,0,nil); LineTo(MyDC,x_center,nHeight); end; procedure polar_to_decart(ro:Extended;fi:Extended); //Процедура переводу координат з полярної системи в декартову begin xd:=ro*cos(fi); yd:=ro*sin(fi); end; procedure paint_graph(A,B:integer;gpen:hPen); {процедура малювання графіку} var i:integer; ro,fi,dfi:Extended; begin selectObject(Mydc,gpen); fi:=1; dfi:=0.001; ro:=A*cot(fi)+B; polar_to_decart(ro,fi); MoveToEx(MyDC,x_center+Round(xd*scale),y_center+Round(yd*scale),nil); while fi<2 do begin ro:=A*cot(fi)+B; polar_to_decart(ro,fi); LineTo(MyDC,x_center+Round(xd*scale),y_center+Round(yd*scale)); fi:=fi+dfi; end; end; procedure paint_graph1(A,B:integer;gpen:hPen;gbrush:hbrush); {процедура малювання графіку замкнутої області} var i:integer; x,y,ro,fi,dfi:Extended; begin selectObject(Mydc,gpen); selectObject(Mydc,gbrush); fi:=1; dfi:=0.001; ro:=A*cot(fi)+B; polar_to_decart(ro,fi); MoveToEx(MyDC,x_center+Round(xd*scale),y_center+Round(yd*scale),nil); while fi<2 do begin ro:=A*cot(fi)+B; polar_to_decart(ro,fi); LineTo(MyDC,x_center+Round(xd*scale),y_center+Round(yd*scale)); fi:=fi+dfi; end; x:=xd; y:=yd; fi:=1; dfi:=0.001; ro:=A*cot(fi)+B; polar_to_decart(ro,fi); LineTo(MyDC,x_center+Round(xd*scale),y_center+Round(yd*scale)); FloodFill(MyDC,x_center-10,y_center+10,rgb(255,0,0)); selectObject(Mydc,pen[2]); LineTo(MyDC,x_center+Round(x*scale),y_center+Round(y*scale)); end; //Тіло програми begin write('scale '); readln(scale); write('step of net '); readln(stepofnet); {Далі йде заповнення шаблону класу вікна} 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); //Реєстрація нового класу в системі nWidth:=600; nHeight:=500; x_center:=nWidth div 2; y_center:=nHeight div 2; xPos:=10; yPos:=10; MainWnd:=CreateWindowEx(0,'WinMin:Main','ЛР №3: Побудова графіків функцій',ws_overlappedwindow,xPos,yPos,nWidth,nHeight,0,0,Hinstance,nil ); ShowWindow(MainWnd,CmdShow); //Відображуємо вікно //Цикл обробки повідомлень While GetMessage(Mesg,0,0,0) do begin TranslateMessage(Mesg); DispatchMessage(Mesg); // робота з графічними функціями GetClientRect(MainWnd,rec); MyDc:=GetDC(MainWnd); pen[1]:=createpen(ps_solid,1,rgb(0,0,0)); pen[2]:=createpen(ps_solid,2,rgb(0,0,0)); pen[3]:=createpen(ps_solid,2,rgb(255,0,0)); pen[4]:=createpen(ps_solid,2,rgb(0,255,0)); pen[5]:=createpen(ps_solid,2,rgb(0,0,255)); brush[1]:=createSolidBrush(rgb(0,0,0)); brush[2]:=createSolidBrush(rgb(255,0,0)); brush[3]:=createSolidBrush(rgb(0,255,0)); brush[4]:=createSolidBrush(rgb(0,0,255)); net; paint_graph(-1,0,pen[3]); paint_graph1(-1,0,pen[3],brush[1]); paint_graph(0,1,pen[4]); paint_graph(-1,1,pen[5]); CreateMetaFile('g.wmf'); ReleaseDC(MainWnd,MyDc); //звільнення зсилки DeleteDC(MyDC); //видалення зсилки end; end. Результат роботи програми:  ВИСНОВОК: В даній лаборатонрій роботі ми ознайомились та практично освоїли технології й основи роботи зграфічними можливостями Windows-інтерфейсу (WinAPI) операційного середовища Wіndows, що можуть викликатися прикладними програмами. Вивчили основні графічні функцій та процедури WinAPI (Win32API) візуального середовища програмування Borland Delphi, набули практичних навиків переходу з програмування графіки для операційної системи DOS до оволодіння принципами створення Wіndows-программ, розробки графічних процедур та програм WinAPI.
Антиботан аватар за замовчуванням

02.10.2020 20:10-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!