Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
программирование и основы алгоритмизации.doc
Скачиваний:
44
Добавлен:
21.08.2019
Размер:
4.84 Mб
Скачать

Графика в оконных приложениях Windows

Система координат для вывода графических образов такая же, как и для ввода текстовой информации. Координаты измеряются в логических единицах, которые по умолчанию совпадают с пикселями. Начало отсчета – верхний левый угол окна.

Для создания графических образов используются 3 основных объекта: точка (пиксел), перо, кисть.

Цвет точки задается с помощью функции

COLORREF SetPixel(

HDC hdc, // дескриптор контекста окна

int X, // x-координата точки

int Y, // y-координата точки

COLORREF crColor); // цвет точки

Перо используется для рисования линий и контуров замкнутых фигур. Цвет пера задается при помощи функции

HPEN CreatePen(

int fnPenStyle, // стиль пера

// PS_SOLID =0

// PS_DASH =1

// PS_DOT =2

// PS_DASHDOT =3

// PS_DASHDOTDOT =4

// PS_NULL =5 невидимое перо

int nWidth, // ширина пера

COLORREF crColor); // цвет пера

Кисть используется для закрашивания замкнутых объектов. Цвет кисти задается с помощью функции

HBRUSH CreateSolidBrush( COLORREF crColor ); // цвет кисти

Можно заранее создать несколько кистей и перьев, а затем выбирать нужные с помощью функции

HGDIOBJ SelectObject(

HDC hdc, // дескриптор контекста окна

HGDIOBJ hgdiobj ); // дескриптор объекта

Обновление информации в окне программы происходит по получению сообщения WM_PAINT. В реальных программах вывод информации в окно может происходить по различным событиям и из различных процедур. Кроме того, если информации в окне много, то непосредственный вывод при помощи функции TextOut достаточно медленный. Чтобы воспроизводить содержимое окна, необходимо где-то запомнить это содержимое. Возникает проблема сохранения информации (и не только текстовой), находящейся в окне.

В операционной системе Windows образуется виртуальное окно, и весь вывод информации производится туда. Затем по приходе сообщения WM_PAINT содержимое виртуального окна копируется на реальное окно. В целом общая схема такова:

1. При создании окна

  • создается совместимый контекст устройства функцией

HDC CreateCompatibleDC( HDC hdc); // дескриптор контекста окна

Полученный контекст следует запомнить.

  • создается карта бит, совместимая с данным контекстом функцией

HBITMAP CreateCompatibleBitmap(

HDC hdc, // дескриптор контекста окна

int nWidth, // ширина пиксельной картинки

int nHeight ); // высота пиксельной картинки

  • выбирается кисть цветом, совпадающим с цветом основного окна.

  • создается битовый шаблон путем выполнения растровой операции с использованием выбранной кисти. Функция перерисовки заданного прямоугольника выбранной кистью

BOOL PatBlt(

HDC hdc, // дескриптор контекста окна

int nXLeft, // x- координата верхнего левого угла

int nYLeft, // y- координата верхнего левого угла

int nWidth, // ширина прямоугольника

int nHeight, // высота прямоугольника

DWORD dwRop); // код растровой операции:

;PATCOPY =0F00021h копирует цвет кисти в окно.

;PATINVERT =5A0049h комбинирует цвет кисти и цвет окна функцией XOR

;DSTINVERT =550009h инвертирует цвет прямоугольника

;BLACKNESS =42h закрашивает прямоугольник черным цветом

;WHITENESS =0FF0062h закрашивает прямоугольник белым цветом

  1. Вся информация выводится в виртуальное окно и дается команда перерисовки окна. Функция

BOOL InvalidateRect(

HWND hWnd, // дескриптор окна

CONST RECT* lpRect, // координаты прямоугольника

BOOL bErase); // при 1 фон стирается, при 0 остается

RECT STRUCT

left dd ?

top dd ?

right dd ?

bottom dd ?

RECT ENDS

  1. При получении сообщения WM_PAINT содержимое виртуального окна копируется на реальное окно. Функция

BOOL BitBlt(

HDC hdcDest, // дескриптор совместимого контекста

int nXDest, // x- координата левого верхнего угла совм. контекста

int nYDest, // y- координата левого верхнего угла совм. контекста

int nWidth, // ширина прямоугольника совместимого контекста

int nHeight, // высота прямоугольника совместимого контекста

HDC hdcSrc, // дескриптор контекста окна

int nXSrc, // x- координата левого верхнего угла контекста окна

int nYSrc, // y- координата левого верхнего угла контекста окна

DWORD dwRop); // код растровой операции

SRCCOPY equ 0CC0020h

SRCPAINT equ 0EE0086h

SRCAND equ 8800C6h

SRCINVERT equ 660046h

SRCERASE equ 440328h

Для рисования можно использовать следующие функции API:

BOOL LineTo( // провести прямую линию выбранным пером

// от текущей точки до указанной точки

HDC hdc, // дескриптор контекста окна

int nXEnd, // x- координата конечной точки

int nYEnd); // y- координата конечной точки

BOOL MoveToEx( // переместить текущую точку

HDC hdc, // дескриптор контекста окна

int X, // x- координата новой текущей точки

int Y, // y- координата новой текущей точки

LPPOINT lpPoint); // указатель на структуру POINT, куда

// поместятся координаты старой текущей точки, может быть равен 0

BOOL ArcTo( // рисование дуги

HDC hdc, // дескриптор контекста окна

int nLeftRect, // x-координата верхнего левого угла

int nTopRect, // y- координата верхнего левого угла

int nRightRect, // x- координата нижнего правого угла

int nBottomRect, // y- координата нижнего правого угла

int nXRadial1, // x- координата конца первого радиуса

int nYRadial1, // y- координата конца первого радиуса

int nXRadial2, // x- координата конца второго радиуса

int nYRadial2); // y- координата конца второго радиуса

BOOL Rectangle( // рисование прямоугольника

HDC hdc, // дескриптор контекста окна

int nLeftRect, // x-координата верхнего левого угла

int nTopRect, // y-координата верхнего левого угла

int nRightRect, // x-координата нижнего правого угла

int nBottomRect); // координата нижнего правого угла

BOOL Ellipse( // рисование эллипса

HDC hdc, // дескриптор контекста окна

int nLeftRect, // x- координата верхнего левого угла

int nTopRect, // y- координата верхнего левого угла

int nRightRect, // x- координата нижнего правого угла

int nBottomRect); // y- координата нижнего правого угла

Для получения размера окна при его изменении используется функция

BOOL GetWindowRect( HWND hWnd, // дескриптор окна

LPRECT lpRect); // указатель на структуру RECT

Для освобождения контекста окна используется функция

int ReleaseDC(

HWND hWnd, // дескриптор окна

HDC hDC); // дескриптор контекста окна

Для удаления контекста окна используется функция

BOOL DeleteDC( HDC hdc ); // дескриптор контекста окна

Для получения сведений о размерах (в пикселях) элементов окна системы используется функция

int WINAPI GetSystemMetrics( __in int nIndex)

nIndex – константа, определяющая необходимую величину для измерений

SM_CXSCREEN=0 каличество точек экрана по горизонтали

SM_CYSCREEN=1 каличество точек экрана по вертикали

SM_CYCAPTION=4 высота строки заголовка

SM_CXFRAME =32 толшина вертикальной рамки окна

SM_CYFRAME =8 толшина горизонтальной рамки окна

Пример: вывести график функции y=sin(t) при t[0,3600].

Вывод точек осуществляется функцией LineTo. Значение координат точек вычисляется по формулам:

X=OffsetX + tScaleX, Y=OffsetY + yScaleY, (*)

где OffsetX, OffsetY – смещения начала отсчета графика относительно начала отсчета окна;

ScaleX, ScaleY – масштабные коэффициенты осей.

Если принять, что данные, возвращаемые функцией GetWindowRect, позволяют вычислить ширину окна Width и высоту окна Height2, то величины в формулах (*) можно определить как

OffsetX = 0, OffsetY = Height/2,

ScaleX = Width/360, ScaleY = 1/(Height/2)=2/Height

; текст программы

.586

.MODEL FLAT, stdcall

RGBW equ 00D4D0C8h ; цвет фона в окне

include win.inc3

.data

HWND DD 0 ; дескриптор главного окна

HINST DD 0 ; дескриптор приложения

TITL DB "Программа",0

CLASSNAME DB 'CLASS32',0

Message MSG <?>

WC WNDCLASS <?>

hdc DD 0 ; дескриптор контекста окна

hPen DD 0 ; дескриптор пера

memdc DD 0 ; дескриптор совместимого контекста окна

Height_ DD ? ; высота окна

Width_ DD ? ; ширина окна

rect_ RECT <>

ps PAINTSTRUCT <?>

messX db 'y=sin(t)',0

mess_len equ $-messX-1

OffsetX DD 0

OffsetY DD ?

ScaleX DD ?

ScaleY DD ?

X DD 0

Y DD 0

t DD 0

cons DD ? ; константа

deg_rad DD 180 ; преобразование из градусов в радианы

.code

START proc

; получить дескриптор приложения

INVOKE GetModuleHandle, 0

MOV HINST, EAX

; заполнить структуру окна

MOV WC.style, CS_HREDRAW+CS_VREDRAW+CS_GLOBALCLASS

; процедура обработки сообщений

MOV WC.lpfnWndProc, OFFSET WNDPROC

MOV EAX, HINST

MOV WC.hInstance, EAX

INVOKE LoadIcon, 0, IDI_APPLICATION

MOV WC.hIcon, EAX

INVOKE LoadCursor, 0, IDC_ARROW

MOV WC.hCursor, EAX

INVOKE CreateSolidBrush, RGBW

MOV WC.hbrBackground, EAX

MOV WC.lpszMenuName, 0

MOV WC.lpszClassName, OFFSET CLASSNAME

INVOKE RegisterClass, OFFSET WC

INVOKE CreateWindowEx,0, ; создать окно зарегистрированного класса

OFFSET CLASSNAME,

OFFSET TITL,

WS_CAPTION + WS_SYSMENU + WS_THICKFRAME + WS_GROUP + WS_TABSTOP,

100, ; X — координата левого верхнего угла

100, ; Y — координата левого верхнего угла

400, ; DX - ширина окна

450, ; DY — высота окна

0, 0, HINST,0

; проверка на ошибку

CMP EAX, 0

JZ END_LOOP

MOV HWND, EAX ; дескриптор окна

INVOKE ShowWindow, HWND, SW_SHOWNORMAL ; показать созданное окно

INVOKE UpdateWindow, HWND ;перерисовать видимую часть окна

; цикл обработки сообщений

MSG_LOOP:

INVOKE GetMessage, OFFSET Message, 0,0,0

CMP EAX, 0

JE END_LOOP

INVOKE TranslateMessage, OFFSET Message

INVOKE DispatchMessageA, OFFSET Message

JMP MSG_LOOP

END_LOOP:

INVOKE ExitProcess, Message.wParam ; выход из программы (закрыть процесс)

START endp

; --------------------------------------------------

; процедура окна

WNDPROC PROC hW:DWORD, Mes:DWORD, wParam:DWORD, lParam:DWORD

CMP Mes, WM_DESTROY

JE WMDESTROY

CMP Mes, WM_CREATE

JE WMCREATE

CMP Mes, WM_PAINT

JE WMPAINT

CMP Mes, WM_SIZE

JE WMSIZE

JMP DEFWNDPROC

WMSIZE:

cmp memdc,0

jne WMCREATE

INVOKE DeleteDC, memdc

; создание окна

WMCREATE:

INVOKE GetDC, hW

mov hdc, eax

INVOKE CreateCompatibleDC, hdc

mov memdc, eax

INVOKE GetWindowRect, hW, offset rect_

mov eax, rect_.bottom

sub eax, rect_.top

mov Height_, eax

mov eax, rect_.right

sub eax, rect_.left

mov Width_, eax

INVOKE CreateCompatibleBitmap, hdc, Width_, Height_

INVOKE SelectObject, memdc, eax

INVOKE CreateSolidBrush, RGBW

INVOKE SelectObject, memdc, eax

INVOKE PatBlt, memdc, 0, 0, Width_, Height_, PATCOPY

INVOKE ReleaseDC, hW, hdc

INVOKE CreatePen, PS_SOLID, 0,0 ; черное перо

mov hPen, eax

INVOKE SelectObject, memdc, hPen

mov eax, Height_

sub eax, 27

shr eax, 1

mov OffsetY, eax

INVOKE MoveToEx, memdc, 0, OffsetY, 0 ; горизонтальная ось

INVOKE LineTo, memdc, Width_, OffsetY

INVOKE CreatePen, PS_SOLID, 2, 000000FFh ; красное перо

mov hPen, eax

INVOKE SelectObject, memdc, hPen

INVOKE MoveToEx, memdc, 0, OffsetY, 0

mov eax, 0

mov t, eax

mov eax, 8 ; GetSystemMetrics(SM_CXFRAME)*2

mov cons, eax

fild Width_

fisub cons

fidiv deg_rad

mov eax, 2

mov cons, eax

fidiv cons

fstp ScaleX

mov eax, 27 ; GetSystemMetrics(SM_CYFRAME)*2 +

mov cons, eax ; GetSystemMetrics(SM_CXFRAME)*2

fild Height_

fisub cons

mov eax, 2

mov cons, eax

fidiv cons

fstp ScaleY

mov ecx, 360

L: push ecx

fild t

fmul ScaleX

fiadd OffsetX

fistp X

fild t

fldpi

fmulp

fidiv deg_rad

fsin

fchs

fmul ScaleY

fiadd OffsetY

fistp Y

inc t

INVOKE LineTo, memdc, X, Y

pop ecx

loop L

INVOKE InvalidateRect, hW, offset rect_,0

INVOKE SetBkColor, memdc, RGBW

mov eax, mess_len

INVOKE TextOutA, memdc, 10, 20,

offset messX, eax ; вывод текста y=sin(t)

MOV EAX, 0

JMP FINISH

; перерисовка окна

WMPAINT:

INVOKE BeginPaint, hW, offset ps

mov hdc,eax

INVOKE BitBlt,

hdc,

0, 0,

Width_, Height_,

memdc,

0, 0,

SRCCOPY

INVOKE EndPaint, hdc, offset ps

MOV EAX, 0

JMP FINISH

; обработка сообщения по умолчанию

DEFWNDPROC:

INVOKE DefWindowProc,

hW,

Mes,

wParam,

lParam

JMP FINISH

WMDESTROY:

INVOKE DeleteDC, hPen

INVOKE DeleteDC, memdc

INVOKE PostQuitMessage, 0

MOV EAX, 0

FINISH:

ret

WNDPROC ENDP

END START

Результат работы программы: