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

5.7. Малювання на екрані маніпулятором "миша"

Приклад роботи малювання на екрані за допомогою мишки знаходиться у папці DISK\GDI\GDI5.

Створимо MDI програму з назвою LineApp, у якій будемо малювати мишею на екрані. Для малювання мишею у вікні додамо у клас виду наступні змінні:

class CLineAppView : public CView

{

.............................................................

CPen pen;

CClientDC* dc;

int nWidth;

};

Де pen – олівець, яким будемо малювати; nWidth – ширина олівця; dc – клієнтський контекст пристрою для малювання. Ініціалізацію змінної nWidth робимо у конструкторі вікна:

CLineAppView::CLineAppView()

{

nWidth = 1;

}

Для створення об’єкту клієнтського контексту вікна створимо функцію OnCreate, яка викликається при появі вікна.

int CLineAppView::OnCreate(LPCREATESTRUCT lpCreateStruct)

{

if (CView::OnCreate(lpCreateStruct) == -1)

return -1;

dc = new CClientDC(this);

return 0;

}

Додамо функцію на натиснення лівої кнопки миші, напишемо у ній наступний код:

void CLineAppView::OnLButtonDown(UINT nFlags, CPoint point)

{

pen.DeleteObject();

pen.CreatePen(PS_SOLID, nWidth, RGB(0,0,0));

dc->SelectObject(&pen);

dc->MoveTo(point);

CView::OnLButtonDown(nFlags, point);

}

При натисненні лівої кнопки миші ми створюємо олівець для малювання у змінній pen, після чого завантажуємо створений олівець у контекст клієнтського вікна dc. Через функцію MoveTo фіксуємо координати курсора миші.

Додамо функцію на переміщення миші, напишемо у ній наступний код:

void CLineAppView::OnMouseMove(UINT nFlags, CPoint point)

{

if(nFlags==MK_LBUTTON)

dc->LineTo(point);

CView::OnMouseMove(nFlags, point);

}

До функції OnMouseMove надходить змінна nFlags, яка зберігає константу натиснення кнопки миші. Так, якщо користувач переміщує мишку та при цьому натиснута ліва кнопка миші – змінна nFlags дорівнює MK_LBUTTON, якщо права кнопка миші – MK_RBUTTON.

Отже, якщо включено режим малювання (nFlags==MK_LBUTTON) то виводимо лінію через функцію LineTo.

Для зміни товщини лінії додамо функцію на натиснення правої кнопки миші, напишемо наступний код:

void CLineAppView::OnRButtonDown(UINT nFlags, CPoint point)

{

nWidth++;

CView::OnRButtonDown(nFlags, point);

}

Результат роботи програми на рис. 5.12:

Рис. 5.12. Малювання мишею ліній у вікні

5.8. Завантаження та виведення на екран бітових зображень

Приклад завантаження та виведення на екран бітових зображень знаходиться у папці DISK\GDI\GDI6.

Створимо SDI-додаток з назвою Kart для роботи з бітовими зображеннями. Роботу з бітовими зображеннями слід розділити на два етапи:

  1. Завантаження бітового зображення.

  2. Виведення на екран бітового зображення.

Завантажувати зображення у форматі *.bmp можна двома засобами: використовуючи файл ресурсів та зчитування зображення безпосередньо з файлу *.bmp.

Зберігання зображення у ресурсах самого додатку збільшить розмір виконавчого *.exe файлу, але при цьому окремі файли зображень стануть непотрібними. Для зчитування зображень із ресурсів програми використовується функція LoadBitmap класу CBitmap.

У даній програмі створюються три ідентифікатори ресурсів для роботи з картинками – IDB_BITMAP1, IDB_BITMAP2 та IDB_BITMAP3. Кожен з цих ресурсів посилається на файл з розширенням *.bmp, відповідно «BMP\audi.bmp», «BMP\BMW.bmp», «BMP\GAZ.bmp».

На рис. 5.13. наведемо властивості ресурсу з ідентифікатором IDB_BITMAP1.

Для зчитування зображення безпосередньо з файлу *.bmp використовується функція WinAPI LoadImage.

Рис. 5.13. Властивості ресурсу Bitmap з ідентифікатором IDB_BITMAP1

Наведемо вхідні параметри цієї функції:

HANDLE LoadImage(

// вказівка на додаток, який містить зображення

HINSTANCE hinst,

// текст з найменуванням файлу зображення

LPCTSTR lpszName,

// тип зображення

UINT uType,

// ширина зображення

int cxDesired,

// висота зображення

int cyDesired,

// прапорці для зчитування

UINT fuLoad );

Розроблена програма завантажує зображення двома засобами – за допомогою зчитування з файлу ресурсів (функція LoadBitmap класу CBitmap) та за допомогою зчитування з файлу *.bmp (функція LoadImage).

Меню «Картинка на экране 1» призначено для роботи з картинками, які завантажуються з ресурсів (Audi, Bmw, Gaz). Цим картинкам відповідають значення змінної kod_graf від 1 до 3. Крім того, тут передбачено включення та виключення таймеру (опції меню «Включить таймер», «Выключить таймер») по якому відбувається почергове виведення картинок – Audi, Bmw, Gaz.

Опція меню «Картинка на экране 2» призначена для роботи з картинкою, яка завантажується з файлу «BMP\opel.bmp».

Опція меню «Коллаж картинок» призначено для виведення колажу картинок на екрані дисплею.

Наведемо функції відгуків кожної з цих опцій меню.

void CKartView::OnM1()

{

kod_graf = 1;

Invalidate();

}

void CKartView::OnM2()

{

kod_graf = 2;

Invalidate();

}

void CKartView::OnM3()

{

kod_graf = 3;

Invalidate();

}

void CKartView::OnT1()

{

//Включення таймеру

SetTimer(1,500,0);

}

void CKartView::OnT2()

{

//Відключення таймеру

KillTimer(1);

}

// Завантаження картинки з файлу

void CKartView::OnK2()

{

//Відключення таймеру

KillTimer(1);

//Перевірка наявності папки і файлу, а також

//структури файлу та отримання дескриптору startBitmap

if(access("BMP",0))

{

MessageBox("Отсутствует папка BMP,\nгде должны находится файлы *.bmp\nдля работы с картинками \n","Внимание!",MB_ICONINFORMATION);

return;

}

if(access("BMP\\opel.bmp",0))

{

MessageBox("В папке BMP отсутствует файл opel.bmp","Внимание!",MB_ICONINFORMATION);

return;

}

//Завантаження картинки з файлу

HBITMAP startBitmap = (HBITMAP)LoadImage(NULL,

"BMP\\opel.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE);

if (!startBitmap)

{

MessageBox("В папке BMP ошибочная структура файла opel.bmp","Внимание!",MB_ICONINFORMATION);

return;

}

else

DeleteObject(startBitmap);

kod_graf = 4;

Invalidate();

}

void CKartView::OnK3()

{

//Відключення таймеру

KillTimer(1);

kod_graf = 5;

Invalidate();

}

У функціях відгуку OnM1, OnM2, OnM3 змінній kod_graf привласнюється значення, відповідно, 1, 2, 3 та визивається метод OnDraw. У функції відгуку OnT1 відбувається включення таймеру за допомогою функції SetTimer:

SetTimer(1,500,0);

У даній функції 1 – це ідентифікатор таймеру, 500 – кількість мілісекунд, через яку спрацює функція OnTimer (повідомлення ON_WM_TIMER()). Це значення відповідає половині секунди. У функції відгуку OnT2 відбувається відключення таймеру за допомогою функції KillTimer з вказанням відповідного ідентифікатору – 1:

KillTimer(1);

Наведемо функцію відгуку OnTimer.

void CKartView::OnTimer(UINT nIDEvent)

{

if(kod_graf==0||kod_graf>2)kod_graf=1;

else kod_graf++;

Invalidate();

CView::OnTimer(nIDEvent);

}

У даній функції відбувається збільшення змінної kod_graf в діапазоні від 1 до 3, що відповідає опціям меню Audi, Bmw, Gaz, після чого спрацьовує Invalidate, який викликає метод OnDraw.

У функції відгуку OnK2 відбувається завантаження картинки з файлу «BMP\opel.bmp». Спочатку використовуючи функцію access перевіряється наявність папки BMP та файлу opel.bmp в ній. Якщо такої папки або файлу не існує – на екрані дисплею з’явиться відповідне повідомлення. Далі, використовуючи функцію LoadImage завантажимо картинку з файлу.

HBITMAP startBitmap = (HBITMAP)LoadImage(NULL,

"BMP\\opel.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE);

Дана функція використовується для контролю та повертає значення 0 при невідповідності формату, або дескриптор startBitmap типу HBITMAP, якщо відкриття пройшло успішно.

Якщо картинку відкрито успішно змінній kod_graf привласнюється значення 4 та визивається метод OnDraw.

У функції відгуку OnK3 відбувається відключення таймеру та змінній kod_graf привласнюється значення 5 після чого визивається метод OnDraw.

Отже всі перелічені функції відгуку викликають метод OnDraw для виведення зображень на екран дисплею.

Наведемо текст даної функції:

void CKartView::OnDraw(CDC* pDC)

{

CKartDoc* pDoc = GetDocument();

ASSERT_VALID(pDoc);

if(!kod_graf)return;

CDC mem;

CBitmap bm;

BITMAP bb;

CRect rect;

mem.CreateCompatibleDC(pDC);

GetClientRect(&rect);

//Завантаження картинки з ресурсу

if(kod_graf>0&&kod_graf<4)

{

//Завантаження картинки

bm.LoadBitmap(IDB_BITMAP1+kod_graf-1);

//Отримання ширини та висоти картинки

//(структура BITMAP)

bm.GetBitmap(&bb);

//Завантаження картинки в контекст пам’яті, та

//виведення її з контексту

mem.SelectObject(&bm);

int x,y;

x = (rect.Width()-bb.bmWidth)/2;

y = (rect.Height()-bb.bmHeight)/2;

pDC->BitBlt(x, y, bb.bmWidth, bb.bmHeight, &mem,

0,0,SRCCOPY);

}

//Завантаження картинки з файлу

if(kod_graf==4)

{

HBITMAP startBitmap = (HBITMAP)LoadImage(NULL,

"BMP\\opel.bmp", IMAGE_BITMAP,0,0, LR_LOADFROMFILE);

bm.Attach(startBitmap);

bm.GetBitmap(&bb);

mem.SelectObject(&bm);

pDC->StretchBlt(0, 0,rect.Width(),rect.Height(),

&mem,0,0,bb.bmWidth,bb.bmHeight,SRCCOPY);

}

//Колаж картинок

if(kod_graf==5)

{

int i,j,kolx,koly;

kolx = 5;

koly = 5;

CRect r1(0,0,rect.Width()/kolx,rect.Height()/koly);

bm.LoadBitmap(IDB_BITMAP1);

bm.GetBitmap(&bb);

mem.SelectObject(&bm);

for(i=0;i<koly;i++)

{

for(j=0;j<kolx;j++)

{

pDC->StretchBlt(r1.left,r1.top, r1.Width(),

r1.Height(),&mem,0,0,bb.bmWidth,

bb.bmHeight,SRCCOPY);

r1.OffsetRect(r1.Width(),0);

}

r1.OffsetRect(-kolx*r1.Width(),r1.Height());

}

}

}

Для виведення картинок на екран дисплею необхідно її спочатку завантажити в контекст пам’яті mem. Створюється даний контекст за допомогою функції CreateCompatibleDC.

Завантаження картинки з ресурсу та її виведення відносно центру вікна продемонстровано у наступному фрагменті коду

//Завантаження картинки з ресурсу

if(kod_graf>0&&kod_graf<4)

{

//Завантаження картинки

bm.LoadBitmap(IDB_BITMAP1+kod_graf-1);

//Отримання ширини та висоти картинки

//(структура BITMAP)

bm.GetBitmap(&bb);

//Завантаження картинки в контекст пам’яті, та

//виведення її з контексту

mem.SelectObject(&bm);

int x,y;

x = (rect.Width()-bb.bmWidth)/2;

y = (rect.Height()-bb.bmHeight)/2;

pDC->BitBlt(x, y, bb.bmWidth, bb.bmHeight, &mem,

0,0,SRCCOPY);

}

За допомогою функції LoadBitmap картинка завантажується з ресурсу. За допомогою функції GetBitmap зчитуємо інформацію щодо розмірів картинки у об’єкт bb структури BITMAP. В залежності від клієнтської області вікна rect та розмірів картинки, розраховуємо відступи x та y для виведення картинки на екран. Виведення картинки робиться за допомогою функції BitBlt.

Функція BitBlt копіює бітовий масив з одного контексту пристрою у інший:

BOOL CDC::BitBlt

(

int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, DWORD dwRop

).

Параметр dwRop визначає растрову операцію, яка використовується при копіюванні бітового масиву з контексту пристрою, заданого параметром pSrcDC у область, що задається параметрами x, y, nWidth та nHeight. Параметри xSrc та ySrc задають верхній лівий кут області контексту пристрою джерела, який і визначає бітовий масив, який треба скопіювати. Для операцій, не вимагаючих бітового масиву у якості джерела, параметр pSrcDC повинен дорівнювати нулю.

У таблиці 5.3 приведено перелік використання растрових операцій:

Таблиця 5.3.

Перелік растрових операцій

Назва растрової операції

Опис

BLACKNESS

задана область замальовується суцільним чорним кольором

DSTINVERT

інвертування поточного заповнення

MERGECOPY

комбінування поточного заповнення з поточним пензлем за допомогою оператора AND

MERGEPAINT

комбінування інвертованого бітового масиву з поточним заповненням за допомогою оператора OR

NOTSRCCOPY

копіювання інвертованого бітового масиву

Продовження таблиці 5.3

Назва растрової операції

Опис

NOTSRCERASE

інвертування результату комбінування поточного заповнення з бітовим масивом за допомогою оператора OR

PATCOPY

заповнення області за допомогою поточного пензля

PATINVERT

комбінування поточного заповнення з пензлем за допомогою оператора XOR

PATPAINT

комбінування інвертованого бітового масиву з поточним пензлем за допомогою оператора OR і комбінування результату цієї операції з поточним заповненням за допомогою оператора OR

SRCAND

комбінування поточного заповнення і бітового масиву за допомогою операції AND

SRCCOPY

заповнення заданої області бітовим масивом

SRCERASE

комбінування бітового масиву і інвертованого поточного заповнення за допомогою операції AND

SRCINVERT

комбінування бітового масиву і поточного заповнення за допомогою операції XOR

SRCPAINT

комбінування бітового масиву і поточного заповнення за допомогою операції OR

WHITENESS

задана область замальовується суцільним білим кольором

Результат виведення картинки відносно центру екрану приведено на рис. 5.14.

Рис. 5.14. Виведення картинки відносно центру екрану

При завантаженні картинки з файлу, коли kod_graf дорівнює 4, відбувається її виведення у клієнтську область вікна. Виведення у задану область робиться за допомогою функції StretchBlt.

pDC–>StretchBlt(0,0, rect.Width(), rect.Height(),

&mem,0,0,bb.bmWidth,bb.bmHeight,SRCCOPY);

Функція StretchBlt копіює бітовий масив одного контексту в інший, змінюючи розміри.

BOOL CDC::StretchBlt

(

int x, int y, int nWidth, int nHeight, CDC* pSrcDC, int xSrc, int ySrc, int nSrcWidth, int nSrcHeight, DWORD dwRop

).

Функція копіює бітовий масив з контексту пристрою, заданого параметром pSrcDC у область, яка задається параметрами x, y, nWidth та nHeight. Параметри xSrc та ySrc визначають верхній лівий кут області контексту пристрою джерела, а параметри nSrcWidth та nSrcHeight – розміри бітового масиву. Якщо параметри nWidth та nSrcWidth мають різні знаки, то вхідний бітовий масив відображується зеркально по вісі x. Якщо параметри nHeight та nSrcHeight мають різні знаки, то вхідний бітовий масив відображується зеркально по вісі OY.

Результат виведення картинки у клієнтській області вікна приведено на рис. 5.15.

При виведенні колажу картинок задається кількість картинок по вісі OX та вісі OY, а потім за допомогою функції StretchBlt відбувається виведення відповідної кількості картинок на екран дисплею.

Результат виведення колажу картинок приведено на рис. 5.16.

Рис. 5.15. Результат виведення картинки у клієнтській області вікна

Рис. 5.16. Результат виведення колажу картинок

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]