- •О.С. Зеленський
- •Розділ 1. Загальні відомості створення додатку windows
- •1.1. Створення додатку Windows за допомогою майстра AppWizard
- •1.2. Варіанти майстрів для різних проектів
- •1.3. Короткий опис sdi програми
- •1.4. Короткий опис mdi програми
- •1.5. Короткий опис простого діалогового додатку
- •Контрольні питання
- •Розділ 2. Повідомлення і команди
- •2.1. Обробка повідомлень
- •2.2. Цикли обробки повідомлень
- •2.3. Карти повідомлень
- •Контрольні питання
- •Розділ 3. Документи та види
- •3.1. Клас додатку
- •3.2. Клас головного вікна
- •3.3. Клас документа
- •3.4. Класи виду
- •Контрольні питання
- •Розділ 4. Робота з клавіатурою, мишею і меню
- •4.1. Робота з клавіатурою
- •4.2. Робота з мишею
- •4.3. Робота з меню
- •Контрольні питання
- •Розділ 5. Виведення на екран
- •5.1. Класи графічних об'єктів
- •5.2. Робота зі шрифтами
- •5.3. Робота з пензликами та малювання графічних фігур
- •5.4. Робота з пензликом
- •5.5. Робота зі скролінгом
- •5.6. Приклад роботи з таблицями
- •5.7. Малювання на екрані маніпулятором "миша"
- •5.8. Завантаження та виведення на екран бітових зображень
- •5.9. Копіювання бітових образів
- •5.10. Малювання графічних об'єктів з використанням резинових контурів та метафайлів
- •5.11. Виділення графічних об'єктів у прямокутній області
- •5.12. Універсальний приклад роботи з двовимірною графікою з використанням резинового контуру
- •5.13. Запис на диск та зчитування з диску графічних об'єктів
- •5.14. Побудова кругових діаграм і гістограм
- •5.15. Користувацький режим роботи з графікою на прикладі малювання годинника Clock
- •Контрольні питання
- •Завдання
- •Розділ 6. Друк і попередній перегляд документів
- •6.1. Вибір і налаштування параметрів друку
- •6.2. Створення контекста пристрою
- •6.3. Друк документів і бібліотека mfc
- •6.4. Масштабування
- •6.5. Друк багатосторінкового документа
- •Контрольні питання
- •Розділ 7. Робота з файлами
- •7.1. Приклад роботи з файлами на основі класів cFile, cStdioFile та потоку fstream
- •7.1.1. Робота з класом cFile
- •7.1.2. Робота з потоком fstream
- •Можливі режими доступу
- •7.1.3. Робота з класом cStdioFile
- •7.2. Серіалізація даних, клас cArchive
- •7.3. Використання реєстру в додатках
- •Контрольні питання
- •Завдання
- •Розділ 8. Діалогові вікна
- •8.1. Створення діалогового вікна та простіші елементи керування
- •8.2. Робота зі списками і комбінованими полями
- •8.3. Ускладнений приклад зі списками
- •8.4. Робота з повзунками
- •8.5. Виведення бітових матриць в діалозі та у вікні виду
- •8.6. Лінійний регулятор, лінійний індикатор, інкриментний регулятор
- •8.7. Стандартні діалоги вибору файлів, шрифтів та кольору
- •8.8. Взаємоз'вязок діалога, документа та виду при розробці додатку
- •8.8.1. Клас cDialDoc
- •8.8.2. Клас cDialView
- •8.8.3. Клас Cdlg
- •8.9. Формування вхідного документа на основі діалогу
- •Контрольні питання
- •Завдання Робота з типовими елементами керування
- •Робота зі списками і комбінованими полями
- •Список літератури
5.9. Копіювання бітових образів
Приклад копіювання бітових образів знаходиться у папці DISK\GDI\GDI7.
У наступному прикладі продемонструємо роботу зі створення та копіювання бітових зображень.
Створимо програму з назвою DDB із MDI інтерфейсом. Принцип роботи програми буде таким:
1) при включенні у вікні виду будуть малюватись 4 прямокутника;
2) при подвійному натисненні кнопкою миші на один із них буде створюватись копія обраної прямокутної області у пам'яті (ця копія контексту екрану вікна буде робитись з використанням класу CBitmap);
3) при подвійному натисненні кнопкою миші не на прямокутну область будемо виводити у вікні раніше скопійовану область екрану, якщо вона буде повністтю вміщатися у вікно;
4) при зміненні розмірів вікна прямокутники зміняться і тому обрана область екрану буде не доступна для виведення на екран.
Додамо у клас виду наступні змінні:
class CDDBAppView : public CView
{
.............................................................
public:
bool was_copied;
BYTE* m_Buffer;
CRect m_Rect;
.............................................................
};
Змінна was_copied буде вказувати на те чи відбулось копіювання прямокутної області, тобто чи користувач натискав на якийсь із прямокутників чи ні. У m_Buffer буде міститись буфер із обраною областю екрану. Призначення прямокутника m_Rect розглянемо далі.
Основна робота програми буде виконуватись у двох функціях це OnDraw і OnLButtonDblClk. Перша функція створюється разом із програмою а другу функцію додамо через майстер. У функції OnDraw будемо виводити прямокутники наступним чином:
void CDDBAppView::OnDraw(CDC* pDC)
{
CDDBAppDoc* pDoc = GetDocument();
ASSERT_VALID(pDoc);
CRect rect;
int wd;
GetClientRect(&rect);
DWORD col[4] =
{
RGB( 0, 0, 0 ),
RGB( 255, 0, 0 ),
RGB( 0, 255, 0 ),
RGB( 0, 0, 255 ),
};
rect.right = (rect.right - 10)/4*4;
m_Rect = CRect( 10, 10, rect.right,10 + height);
wd = m_Rect.Width()/4;
rect = m_Rect;
rect.right = rect.left + wd;
for(int i = 0; i < 4; i++)
{
pDC->FillRect(rect,&CBrush(col[i]));
rect.OffsetRect(wd,0);
}
was_copied = false;
}
У прямокутнику m_Rect будуть зберігатись координати області із усіма прямокутниками. Локальна змінна rect потрібна для виведення на екран окремих прямокутників.
Функція GetClientRect визначає розміри клієнтського вікна. На рис.5.17. приведено результат виведення прямокутників.
Рис. 5.17. Виведення прямокутників у контексті вікна
Функція OnLButtonDblClk котра реагуватиме на подвійне клацання мишею має такий вид:
void CDDBAppView::OnLButtonDblClk(UINT nFlags, CPoint point)
{
CClientDC pDC( this );
CDC memDC;
CBitmap m_Bitmap;
int size;
int wd = m_Rect.Width()/4;
m_Bitmap.CreateCompatibleBitmap
( &pDC, wd, m_Rect.Height() );
BITMAP bm;
m_Bitmap.GetBitmap(&bm);
// size - розмір
// bm.bmWidth - ширина бітового образу
// bm.bmHeight - висота бітового образу
// bm.bmBitsPixel - кількість біт на піксель;
size = bm.bmWidth*bm.bmHeight*bm.bmBitsPixel/8;
if(!m_Buffer)
m_Buffer = new BYTE[size];
memDC.CreateCompatibleDC( &pDC );
CBitmap* oldBitmap = memDC.SelectObject( &m_Bitmap );
if( m_Rect.PtInRect( point ) )
{
int nRect = (point.x - m_Rect.left)/wd;
memDC.BitBlt(0, 0, wd, height, &pDC,
m_Rect.left + nRect*wd, 10, SRCCOPY);
m_Bitmap.GetBitmapBits(size, m_Buffer);
was_copied = true;
}
else
{
CRect rect;
GetClientRect( rect );
if( was_copied && (point.x < (rect.right - wd)) &&
(point.y < (rect.bottom - height)) )
{
m_Bitmap.SetBitmapBits(size, m_Buffer );
pDC.BitBlt(point.x, point.y, wd, height, &memDC, 0,
0, SRCCOPY);
}
}
memDC.SelectObject( &oldBitmap );
CView::OnLButtonDblClk(nFlags, point);
}
Спочатку функції ми підготовлюємо об’єкти: pDC, memDC, m_Bitmap і bm. Змінна wd буде містити ширину прямокутника у пікселях. Змінна size потрібна для обчислення кількості байтів для зберігання бітового зображення. Кількість байтів у бітовому образі обчислюється за формулою: ширина образу * висота образу * кількість біт у пікселі / 8. Далі створюємо контекст у пам’яті memDC, за допомогою функції CreateCompatibleDC.
Функція PtInRect із класу CRect перевіряє чи потрапляє точка у прямокутник. У прямокутнику m_Rect знаходиться область, яку займають прямокутники. Отже в умові if відбувається перевірка чи потрапили ми при натисненні у будь-який із цих прямокутників. Якщо потрапили у область m_Rect, тоді обчислюємо у змінній nRect номер прямокутника, на якому ми натиснули.
Механізм роботи з виведенням бітових зображень полягає у наявності двох контекстів: контексту для малювання pDC та контексту пам’яті memDC. Так, зображення можна виводити з одного контексту в інший і навпаки.
Для того щоб вивести зображення в контекст пам’яті memDC з контексту малювання pDC скористаємось функцією BitBlt у наступному рядку коду.
memDC.BitBlt(0, 0, wd, height, &pDC,
m_Rect.left + nRect*wd, 10, SRCCOPY);
За допомогою цього рядку у контекст пам’яті записується бітовий образ прямокутника з номером nRect. Бітовий образ фактично записується до об’єкту m_Bitmap класу CBitmap, так як у функції SelectObject завантажується саме цей бітовий образ. Після запису в бітовий образ прямокутнику за допомогою GetBitmapBits класу CBitmap відбувається запис кольорів пікселів до масиву m_Buffer. При цьому змінній was_copied привласнюється значення true, що говорить про те, що бітовий образ з вибраним прямокутником знаходиться в пам’яті.
Для того щоб вивести зображення на екран дисплею з пам’яті, його спочатку треба завантажити до контексту memDC, а потім, використовуючи функцію BitBlt, вивести його на екран. Це відбувається наступним чином.
m_Bitmap.SetBitmapBits(size, m_Buffer );
pDC.BitBlt(point.x, point.y, wd, height, &memDC, 0,
0, SRCCOPY);
Спочатку в об’єкт m_Bitmap записується масив кольорів пікселів бітового образу за допомогою функції SetBitmapBits, а потім за допомогою функції BitBlt прямокутник виводиться на екран дисплею у заданому місці.
При зміні розміру вікна (функція OnSize) прямокутники будуть перемальовані, отже треба зробити видалення масиву кольорів пікселів m_Buffer та змінній was_copied привласнити значення false. Наведемо текст даної функції.
void CDDBAppView::OnSize(UINT nType, int cx, int cy)
{
if(m_Buffer)
{
delete []m_Buffer;
m_Buffer = 0;
}
was_copied = false;
CView::OnSize(nType, cx, cy);
}