Робота з зображеннями C + + Builder

Windows – це графічна операційна система, CBuilder – графічна середовище розробки для C + +, WWW переповнений графікою Всі ці речі мають відношення до зображень і обробці зображень, і в цій главі ми розглянемо обробку зображень у CBuilder

Графіка – це занадто захоплюючий предмет для того, щоб вивчати її на основі сухих казенних прикладів, і тому ми трохи попустувати, вивчаючи графічні аспекти CBuilder За допомогою CBuilder ми створимо дві простенькі ігри – гра збігів (Match Game) і хрестики-нулики Обидві нададуть можливість злегка розважитися, вивчаючи систему Незважаючи на те що ці ігри навряд чи зможуть ощасливити кого-небудь не найрозумнішим менеджера довше, ніж на кілька хвилин, вони принаймні зможуть хоч ненадовго зайняти того трирічного лобуря, що мешкає у вас вдома

Для першого прикладу обробки зображень давайте створимо просту гру Match типу тієї, в яку ви напевно грали в дитинстві, – де треба знайти парні однакові картинки Ви, може бути, знайомі також з версіями цієї гри типу Match або Concentration А от як збираємося відтворити цю гру ми Ігрове поле складається з 16 кнопок, розташованих у сітці 4ґ4, і на кожній кнопці написано її назву Якщо ви виберете дві кнопки з однаковими назвами, вони зникнуть і вам відкриється шматочок картинки, розташованої під кнопками

Для втілення ігрового поля нам будуть потрібні два різних типи обєктів VCL (Visual Component Library): кнопки і зображення (image) Цей приклад показує, як використовується керуючий елемент-зображення і як можна відобразити його на екрані У даному випадку нам нічого не доведеться робити самим – CBuilder все зробить за нас Після того як ми напишемо всю гру цілком, включаючи малювання растрової картинки, організацію всіх кнопок, перевірку їх на збіг і їх видалення в разі збігу, і все в 25 рядках коду (включаючи коментарі), ви побачите всю дійсну потужність CBuilder

Ви знайдете повний вихідний текст програми Match Game на прикладеному до книги компакт-диску

Перше, що вам слід зробити, – це створити ігрове поле Покладіть на форму керуючий елемент – зображення (TImage) і розтягніть його так, щоб він зайняв весь внутрішній простір форми Встановіть властивість Picture (Картинка) на вподобану вам картинку Ми повернемося до того, як завантажити задану картинку, трохи пізніше Поверх зображення вам треба покласти чотири рядки, які перебувають (каждая) з чотирьох кнопок Поки що зробіть властивість Caption кожній з них порожнім рядком На рис 31 показано, як виглядатиме закінчене ігрове поле

Рис 31 Форма CBuilder – поле гри Match Game

Ви можете подумати, що тепер вам доведеться вибирати кожну з 16 кнопок і для кожної встановлювати властивість Caption в порожній рядок, але насправді це не так Виберіть відразу всі кнопки, клацнувши мишею на кожній, тримаючи клавішу Shift Тепер перейдіть на сторінку Properties в Object Inspector Там будуть відображені тільки ті властивості, які можуть бути встановлені для безлічі обєктів (очевидно, що, наприклад, не Name (імя)) Виберіть властивість Caption і видаліть вміст поля властивості Натисніть Enter, і у всіх обєктів заголовки стануть порожніми

Після того як ви очистили заголовки всіх кнопок, не завадило б задуматися і про встановлення осмислених заголовків, щоб можна було порівнювати їх Ми будемо робити це в методі FormCreate (Створення форми), який викликається, коли форма вперше створюється в додатку

Перед тим як розташовувати заголовки на кнопках у специфічному порядку, нам треба створити список можливих заголовків Оскільки я великий шанувальник класичного серіалу «Star Trek», ми будемо використовувати імена персонажів з нього Змініть, як показано нижче, вихідний файл Unitcpp, щоб визначити заголовки Після того як ви введете вихідний текст, ми зможемо поговорити про те, як працює конкретно ця функція

Введіть показані нижче рядка в початок вихідного файлу Це визначаються заголовки для кнопок Оскільки у нас 16 кнопок і ми хочемо, щоб для кожної знайшлася б їй відповідна, нам буде потрібно 8 імен, кожне з яких буде використано на двох кнопках

char *strNames[] = { &quotKirk&quot,

&quotSpock&quot,

&quotMcCoy&quot,

&quotUhura&quot,

&quotSulu&quot,

&quotChekov&quot,

&quotScotty&quot,

&quotRiley&quot,

}

/ / А ось змінений метод FormCreate

void __fastcall TForm1::FormCreate(TObject *Sender)

{

int nStringIndex = 0

for ( int i=0i&ltControlCount++i )

{

TButton *pButton = dynamic_cast&ltTbutton *&gt(Controls[i])

if ( pButton )

{

pButton-&gtCaption = strNames[ nStringIndex ] nStringIndex++

if ( nStringIndex &gt 7 ) nStringIndex = 0

}

}

}

Що ж насправді відбувається в цьому методі

Першою

загадкою є властивість

ControlCount, Яке використовується в заголовку циклу ВластивістьControlCount  (Кількість

керуючих елементів) містить кількість дочірніх керуючих елементів на формі У нашому випадку на формі розпорядженні ся 16 кнопок і одне зображення, так що властивість ControlCount нашої форми має значення 17 Ми обходимо всі дочірні елементи, використовуючи властивість форми Controls (Керуючі елементи)

Властивість Controls класу Form містить покажчики на кожен керуючий елемент, що знаходиться на формі Ви можете звертатися до будь-якого з них абсолютно однаково, оскільки всі ці керуючі елементи якось повязані один з одним у ієрархії VCL У властивості Controls насправді зберігаються обєкти класу TControl, Який є базовим класом для всіх керуючих елементів у системі CBuilder

Після того як ми отримали покажчик на керуючий елемент, нам необхідно дізнатися, чи є цей елемент кнопкою або ж будь-яким іншим керуючим елементом Якщо вам доводилося працювати в інших системах, то, швидше за все, вам доводилося використовувати що-небудь типу IsKindOf або навіть перевіряти контрольні значення обєкта У CBuilder є варіант кращий – функція dynamic_cast стандарту ANSI C + +

Функція dynamic_cast в C + + в загальному випадку має наступний синтаксис: T * pObject = dynamic_cast (somepointer)

де T – Це тип, до якого ви хочете перетворити покажчик, а somepointer – Покажчик на інший обєкт Якщо somepointer не є покажчиком, то компілятор видасть помилку і програма не буде скомпільована

Ви, напевно, памятаєте метод static_cast, Про який ми говорили в минулій чолі, який ближче до нормального варіанту роботи в C + + з перетворення обєктів У разі, якщо аргумент somepointer дорівнює NULL або некоректний (не є покажчиком), static_cast не виконається, і тільки У свою чергу, dynamic_cast спрацює коректно, тільки якщо обєкт, який ви хочете перетворити, відноситься до потрібного типу Для коду наведеної вище функції це означає, що кожен елемент масиву Controls буде приведений до вказівником на обєкт класу TButton, Тільки якщо цей керуючий елемент дійсно є обєктом класу TButton

Останнє твердження справедливо, але неповно Якщо є покажчик на клас, що успадковує від TButton, наприклад певний самим програмістом клас типу TMyButton, перетворення спрацює, і в результаті все одно буде отриманий правильний покажчик на TButton Це одне з чудес поліморфізму, концепція якого говорить, що наследующие класи поводяться точно так само, як і їх базові класи

Після того як ми отримали покажчик на обєкт – кнопку, інше просто Все, що ми робимо,

– Це переміщаємося по іменах в масиві strNames Коли ми доходимо до його кінця, ми просто перевстановлюємо лічильник індексу на початок

Наступним кроком після того, як всіх кнопках були присвоєні деякі значення, буде перевірка на збіг Тут нам дуже допоможе можливість VCL ставити у відповідність кільком обєктам один і той ж обробник події Виберіть всі кнопки на формі, клацнувши по кожній мишею, утримуючи клавішу Shift Перейдіть на сторінку Events в Object Inspector і додайте обробник для події OnClick У полі введення в правій частині сітки введіть імя HandleButtonClick Цей метод буде створений і асоційований з кожною кнопкою форми Ось код для методу HandleButtonClick:

void __fastcall TForm1::HandleButtonClick(TObject *Sender)

{

TButton * pButton = static_cast (Sender) if (m_nClick == 1) / / Другий клацання

{

/ / Скидаємо номер клацання

m_nClick = 0

if ( m_pPrevButton == NULL )

return

/ / Порівнюємо заголовки двох кнопок

if ( m_pPrevButton-&gtCaption == pButton-&gtCaption )

{

m_pPrevButton-&gtHide() pButton-&gtHide()

}

else

{

MessageBeep(MB_ICONEXCLAMATION)

}

}

else

{

/ / Перше клацання

m_nClick = 1

/ / Зберігаємо кнопку

m_pPrevButton = pButton

}

}

Зверніть увагу на те, що тут ми вперше в нашому оповіданні використовуємо аргумент функції Sender Коли CBuilder викликає обробник події для форми (або іншого обєкта), обєкт, який викликав появу події, завжди передається в обробник події як значення аргументу Sender Оскільки ми клацаємо на кнопці, кнопка, на якій ми клацнули, і буде передана методу як значення аргументу Ми повинні перевірити, чи збігається кнопка, натиснута користувачем, з тією, яку він натискав перед нею Для виконання цього нам треба додати пару змінних в клас форми Змініть заголовний файл форми, як показано нижче (зміни виділені підсвічуванням):

< Попередній код опущений для економії місця> void __ fastcall FormCreate (Tobject * Sender)

private // User declarations TButton *m_pPrevButton int m_nClick

public // User declarations

__fastcall TForm1(TComponent* Owner)

}

Аргумент m_pPrevButton буде використовуватися для зберігання покажчика на попередню натиснуту кнопку Значення аргументу m_nClick буде використовуватися для визначення, який же це клацання на формі (перший або повторний) Тепер, нарешті, змініть конструктор форми, щоб ініціалізувати ці змінні класу (це те, що вам завжди доведеться робити в ваших додатках)

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

m_nClick = 0 m_pPrevButton = NULL

}

Коли користувач натискає кнопку в перший раз, викликається метод HandleButtonClick У цей момент змінна m_nClick дорівнює 0 і покажчик на попередню кнопку (m_pPrevButton) Дорівнює NULL Метод HandleButtonClick починає виконуватися з секції else, Де покажчик на попередню кнопку встановлюється на натиснуту кнопку Крім того, змінної m_nClick присвоюється значення 1, що означає для форми, що кнопка була натиснута і тепер буде зроблена спроба знайти кнопку, їй відповідну

Наступного разу, коли натискається кнопка, метод звертається до першої частини секції if, Яка виглядає так:

if (m_nClick == 1) / / Другий клацання

Далі в цій секції ми перевіряємо наявність попередньої кнопки (проста обережність, щоб уникнути фатального збою програми у випадку, якщо ми щось забули) Після цього ми запитуємо у попередньої кнопки її властивість Caption і порівнюємо його з властивістю Caption кнопки, яку ми тільки що обрали Якщо вони однакові, ми «ховаємо» обидві кнопки, викликавши метод Hide (Заховати) для кожної з них Це відкриває знаходиться під ними керуючий елемент Image і показує нам шматочок зображення, що виглядає з глибин ігрового поля Якщо дві кнопки не збігаються, то (за допомогою функції Windows API MessageBeep) Система породжує сигнал спікера

Хоча ми і використовували метод Hide в коді нашого прикладу, ви могли б настільки ж легко впоратися із завданням, встановлюючи в коді програми властивість Visible (видимий) кожної кнопки в false Код, який здійснює це, виглядає так:

m_pPrevButton-&gtVisible = false pButton-&gtVisible = false

На рис 32 показано вікно частково завершеної гри Match Game, на якому деякі кнопки вже прибрані і на ігровому полі між рештою кнопками проглядає зображення

Рис 32 Частково завершена гра Match Game

Джерело: Теллес М – Borland C + + Builder Бібліотека програміста – 1998

Схожі статті:


Сподобалася стаття? Ви можете залишити відгук або підписатися на RSS , щоб автоматично отримувати інформацію про нові статтях.

Коментарів поки що немає.

Ваш отзыв

Поділ на параграфи відбувається автоматично, адреса електронної пошти ніколи не буде опублікований, допустимий HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>

*

*