- •Теоретичні основи Основні поняття
- •Поняття графічний контекст
- •Визначення dc для об’єктів типу вікно
- •Поняття растру та основні функції роботи з ним.
- •Мал. 3. Приклад малювання ламаної фігури Окрім прямої і точки є функції для малювання готових фігур, як коло(еліпс) прямокутник(квадрат).
- •Створення інструментів.
- •Створення пера
- •Створення щитки
- •Створення об’єкта шрифт
- •Створення регіональних контурів
- •Створення об’єкту типу bitmap (полотно)
Лабораторна робота №6
Тема: Використання GDI інтерфейсу для побудови графіки в ОС Windows.
Мета: Навчитися користуватися засобами GDI.
Теоретичні основи Основні поняття
Розпочнемо з того, що собою представляє GDI, і яку роль грає у ОС Windows.
GDI розшифровується як Graphics Device Interface, і є інтерфейсом, який Windows використовує для малювання 2d графіки. Також це найповільніший спосіб відображення графіки з тих, що існують, проте найпростіший для розуміння основ. Отже, спершу, поговоримо про основні поняття і терміни в GDI.
Почнемо з того, що GDI зазвичай не використовують для створення "крутих" графічних ефектів, для цього є DIRECTX, OPENGL. Проте, для створення простих ефектів з мінімальними зусиллями GDI цілком підходить.
Поняття графічний контекст
Для висвітлення або відтворення (наприклад, на папері) малюнка потрібен пристрій виводу(малювання). Наприклад, в моніторі зображення відтворює 3 лазерними пушками, які контролюються 4-ма магнітами, дякуючи їм, лазери будуються складні кольори та контори, що ми бачимо на екрані. Також цей "пристрій" може виступати як певний механізм, що оперує деякою палітрою компонентів. Якщо перейти до абстрактного мислення, то таким пристроєм можна назвати руку людини. Це геніальний пристрій, котрий може намалювати все що завгодно, починаючи від простої точки закінчуючи складною фігурою з тінями і у кольоровому супроводі. У технології GDI є свій пристрій малювання, який може реалізувати, практично все, його називають графічним контекстом або контекстом пристрою (DC - "Device Context").
Визначення dc для об’єктів типу вікно
У операційній системі Windows будь яке вікно, що відтворюється на екрані є малюнком. Виходячи з попереднього твердження, кожне вікно, це графічний об’єкт. Відповідно всі вікна мають свій DC. Щоб ним скористатися, потрібно його визначити (позичити). Це робиться за допомогою функції GetDC.
У функції є один параметр, хендл вікна. Якщо вікна оголошені як діалогові (див. попередню лабораторну), для визначення хенду контрола використовується функція GetDlgItem.
Функція GetDC позичає DC у вікна, тому після використання потрібно повернути DC власнику, тобто вікну. Це робиться за допомогою функції ReleaseDC. Для взяття DC робочого столу параметром функції GetDC має бути "0". Таке значення хендлу працює тільки у вище згаданій функції. В інших випадках може причинити помилку.
GetDC
hWnd // хендл вікна у котрого позичимо DC
Результат: хендл DC
ReleaseDC
hWnd // хендл вікна у кого позичали DC
hDC // хендл DC
Результат: TRUE (1) якщо повернувся DC вікну
Створити DC не можна його можна або позичити або скопіювати за допомогою функції CreateCompatibleDC. Параметр 1, хендл DC з кого копіюємо. Якщо графічний об’єкт з якого будемо чорно-білий, то "ново спечений" DC також буле чорно-білим.
Поняття растру та основні функції роботи з ним.
Перед тим як використовувати методи GDI, треба зрозуміти яким чином відтворюється графіка у комп‘ютері.
Почнемо з того, що таке растр. Растр - це є сукупність мінімальних одиниць зображення, що розміщено як матриця, де під мінімальною одиницею розуміється піксекль. Піксель це точка, але у комп‘ютерній графіці, точна не є круглою, як ми звикли уявляти, а на справді маленький квадратик. Відповідно сукупність пікселів розміщених послідовно ми будемо називати лінією.
Найпростішою і мабуть най повільнішою функцією у GDI є SetPixel.
SetPixel
HDC // хендл DC
X // координата Х
Y // координата Y
crColor // колір у колуванні RGB
Результат: значення встановленого кольору(RGB), або -1 якщо точка розміщена поза зоною видимості
Для взяття інформації про піксель використовується функції GetPixel
GetPixel
HDC // хендл DC
X // координата Х
Y // координата Y
Результат: значення встановленого кольору(RGB) у координатах Х,Y
Під RGB кодування розуміється представлення кольору у вигляді 3 компонентів R – червонного, G – зеленого та B – синього. Кожна компонента займає 1байт, і містить число у діапазоні [0..255]. Це кодування має іншу назву, 24бітний колір (24 bit Color). У ОС Windows використовується 5 типів:
1 bit – чорно біле
4 bit – палітра 16 кольорів (DOS)
8 bit – палітра з 256 кольорів
24 bit – RGB
32 bit – RBG + Alpha (компонента прозорості)
Приклад, градієнт:
Задача: Якщо по вертикалі, в позиції 0 колір буде рівний 0, а в позиції "висота" = 255, то який колір буде в позиції y?
сol = y * 255 / висоту.
;Код 1
.data
hdc1 dd 0
x dd 0
y dd 0
.code
........
.if wParam == 1001
invoke GetDC,hWin
mov hdc1,eax
mov x,0
mov y,0
.while y<270
.while x<500
invoke MulDiv,y,0ffh,270
invoke SetPixel,hdc1,x,y,eax
inc x
.endw
inc y
mov x,0
.endw
invoke ReleaseDC,hWin,hdc1
........
Прапор:
;Код 2
.data
hdc1 dd 0
x dd 0
y dd 0
.code
........
.if wParam == 1001
invoke GetDC,hWin
mov hdc1,eax
mov x,0
mov y,0
.while y<270
.while x<500
; синій зменшується, а червоний та зелений збільшуються
invoke MulDiv,y,0ffh,270
mov ecx,0ffh ; ecx = 255
sub ecx,eax ; ecx – "pos gradient"
shl ecx,16 ; ecx -> blue (<< 16)
mov ebx,eax ; ebx= red
shl eax,8 ; eax = green
or eax,ebx ; mix
or eax,ecx
invoke SetPixel,hdc1,x,y,eax
inc x
.endw
inc y
mov x,0
.endw
invoke ReleaseDC,hWin,hdc1
........
Код1 Код2
Мал. 1. Приклад роботи з пікселями
Для малювання прямих використовується функція LineTo
LineTo
hdc // хендл DC
nXEnd, // координата Х кінця малювання прямої
nYEnd // координата Y кінця малювання прямої
Результат: не нуль, в позитивному випадку
Зверніть увагу, колір, тип та товщина лінії залежить від інструменту (Pen), який використовує на час виконання функції DC, якщо є потреба малювати іншим пером, треба підмінити його новим, про це пізніше.
Початкові координати прямої будуть кінцем попередньої функції, тому якщо є потреба під коректувати це значення використовується функція MoveToEx
MoveToEx
hdc // хендл DC
nXNew, // координата Х
nYNew // координата Y
lpPoint // вказівник на структуру POINT де будуть записані старі координати початку малювання прямої. Цей параметр може бути 0 (NULL)
Результат: не нуль, в позитивному випадку
Наступний приклад ілюструє малювання лінії за рухом мишки.
DlgProc proc hWin:HWND,uMsg:UINT,wParam:WPARAM,lParam:LPARAM
mov eax,uMsg
.if eax==WM_INITDIALOG
invoke GetDC,hWin
mov hdc1,eax
.elseif eax == WM_MOUSEMOVE
; в lParam знаходить х та у [y= HiWord(lParam);x = LoWORD(lParam)]
mov ecx,lParam ; ecx – буде y
mov eax,ecx ; eax - буде x
shr ecx,16
and eax,0ffffh
invoke LineTo,hdc1,eax,ecx
.elseif eax==WM_CLOSE
invoke ReleaseDC,hWin,hdc1
invoke EndDialog,hWin,0
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
DlgProc endp
Мал 2. Приклад малювання лінії
Можна безкінечно удосконалювати програму, зробивши, наприклад, малювання тільки тоді, коли натиснута кнопка Ctrl (це можна визначити за допомогою функції GetKeyState), але на цьому зупинятися не будемо. Спробуйте реалізувати це самі.
Для побудови ламаної лінії у виді фігури, наприклад трикутника, можна намалювати послідовність ліній з відповідними координатами або скористатися однією з функцій для побудові полі-ліній, наприклад PolylineTo.
PolylineTo
hdc // хендл DC
*lppt // вказівник на масив структур POINT, в яких буде міститися координати вершин ламаної
cCount // к-сть вершин
Результат: не нуль, в позитивному випадку
Переглянути функції :
Polyline
PolyPolyline
PolyBezierTo
PolyDraw
Polygon
Приклад побудови трикутника за допомогою ліній:
.data
Hdc1 dd 0
.code
.....
.if wParam == 1001
invoke GetDC,hWin
mov hdc1,eax
invoke MoveToEx,hdc1,100,100,0
invoke LineTo,hdc1,150,150
invoke LineTo,hdc1,250,100
invoke LineTo,hdc1,100,100
invoke ReleaseDC,hWin,hdc1
.endif
......
За допомогою полі-ліній:
.data
hdc1 dd 0
x POINT <150,150>
POINT <250,100>
POINT <100,100>
.code
........
.if wParam == 1001
invoke GetDC,hWin
mov hdc1,eax
invoke MoveToEx,hdc1,100,100,0
invoke PolylineTo,hdc1,addr x,3
invoke ReleaseDC,hWin,hdc1
.endif
........
Результат: