Створення пакетних бібліотек (пакеджів) у C Builder 4

Розміщення наскрізного посилання

Створення пакетних бібліотек (пакеджів) у C++Builder 4

Створення користувацьких компонент

Частина 1. Нові стандарти створення компонентів

Створення додатків у C++Builder побудовано його компонентно-ориентированной архітектурі. Інакше кажучи, вся складність функціональності прихована всередині компонентів. Коли вам потрібно отримати доступ до бази даних, ви використовуєте компоненти замість того, щоб викликати безпосередньо функції з бібліотеки класів. Система C++Builder ідеальна для створення повторно використовуваних "чорних ящиків", що інкапсулюють у собі функціональність. C++Builder робить створення додатків дуже легкою справою, навіть якщо ви нічого не знаєте про те, як влаштовані компоненти та як їх створювати.

Існує дві групи програмістів у C++Builder - користувачі компонентів та їх творці. Коли програмісту потрібно написати програму швидко, він використовує компоненти. З іншого боку, щоб реалізувати нові рішення створюються нові компоненти. Компонентно-орієнтована технологія відкриває собою цілу нову епоху в програмуванні на C++.

При створенні компонентів C++Builder існує три рівні складності. Перший (і найлегший) – завдання нових значень властивостям вже існуючих компонентів. Другий – коли ви розширюєте новими властивостями та методами функціональність компонентів-предків, від яких успадкуєте. І нарешті, третій, найскладніший рівень передбачає створення компонентів або з нуля, або майже з нуля (якщо ви майже повністю переписуєте існуючий компонент). У цій статті описується лише перший рівень.

Компоненти як класи

Щоразу, коли компонент міститься форму, C++Builder створює новий екземпляр його класу. Наприклад,коли користувач кладе форму DBNavigator, C++Builder створює новий об'єкт (з ім'ям DBNavigator1) класу TDBNavigator. Щоб створити новий компонентний клас, використовується успадкування, яке дозволяє взяти з класу-предка потрібні методи та властивості, перевизначити деякі з них та додати свої методи та властивості. Для доступу до компонентів використовуються спеціальні контейнери. Ці контейнери називають пакетними бібліотеками (або пакеджами).

У цьому розділі описано створення пакеджа нового компонента. Якщо ви вже знайомі з архітектурою та методами розробки пакеджів C++Builder, то можете його пропустити.

Пакеджі C++Builder - контейнери для компонент. Вони являють собою DLLs особливого вигляду з розширенням .BPL. Пакедж дозволяє створювати екземпляри об'єктів, що містяться в ньому - це головна його відмінність від звичайної DLL. Усі стандартні компоненти C++Builder перебувають у пакеджах. У C++Builder також існує різниця між пакеджами дизайну (design-time packages), які використовуються тільки всередині IDE, і пакеджами виконання (run-time packages), які необхідно постачати разом із додатком, якщо він динамічно використовує їхній код. Таке рішення дозволяє розділяти код пакеджів між різними додатками C++Builder на одній машині і створює інші зручності. Докладно це описано у довідці та документації.

бібліотек

Мал. 1. Редактор пакеджів

Після того, як пакедж створений і названий, до нього можна додавати нові компоненти (модулі). Далі у статті з прикладу створення нового компонента описано, як вибірково перепризначити значення за промовчанням властивостей існуючого компонента.

Створення нового компонента

Напевно, найпростіший тип компонент, який можна створити в C++Builder - це той, якийпросто задає нові значення за промовчанням деяких властивостей свого предка. Часто програмісти роблять одні й самі операції, що вони кладуть на форму компонент і змінюють щоразу той самий набір властивостей, задаючи самі значення. У цій ситуації було б зручно просто перевизначити значення властивостей за умовчанням у новому компоненті.

бібліотек

Мал. 2. Редактор пакеджів дозволяє додати існуючий компонент.

Сторінка New Component показано на рис.3. Цей компонент названий нами TDefaultedDBNavigator. TDBNavigator завжди має за промовчанням усі кнопки, а також вимкнену опцію ToolTips. У цьому прикладі він змінений так, щоб показувалися тільки чотири кнопки і завжди показувалися підказки ToolTips. Новий компонент буде додано на сторінку панелі з ім'ям Informant (можна створювати нові сторінки, поставивши нові імена). У полі unit file name задається шлях ім'я та шлях до файлів із вихідним текстом.

створення

Мал. 3. Сторінка New Component.

У C++Builder поєднання заголовного файлу та файлу з вихідним кодом називається модуль("unit"). Також у C++Builder прийнято додавати букву "T" перед ім'ям класу. Це залишилося від Object Pascal, який нечутливий до регістру символів. Так передбачалося відрізняти імена класів від змінних.

Майстер створює скелет вихідного тексту компонента. Заголовковий та основний файли показані нижче:

Також у цьому файлі ми бачимо поки що порожній конструктор. Він включає в свій список ініціалізації членів виклик конструктора предка. Це зроблено для зручності. Одна з класичних помилок у створенні компонент Delphi/C++Builder - забути викликати конструктор предка, який, своєю чергою, викликає по ланцюжку конструктори своїх предків. Цей виклик ніколи не можна видаляти.

Примітка перекладача:Вся справа в тому, що VCL написана на Object Pascal, а в ньому, на відміну від C++, при створенні екземпляра нащадка автоматично викликається лише конструктор нащадка, а конструктори предків автоматично не викликаються, так що для коректної роботи їхнеобхідно викликати вручну. Таким чином виходить, що Object Pascal (і, відповідно, всередині VCL) порядок виклику конструкторів зворотний тому, що прийнятий в C++.

Остання функція в цьому файлі – Register, яка викликається всередині спеціального простору імен. Ця функція реєструє компонент(и) з даного модуля(пакеджа) на панелі. Ім'я сторінки палітри, задане в майстрі, міститься тут і його можна поміняти.

Щоб перевизначити значення властивостей за умовчанням, треба просто задати їм нові значення конструкторі. Отже, щоб створити новий навігатор зі старого, потрібно додати в конструктор три лінії коду. Модифікований конструктор показано нижче. Спочатку очищається безліч кнопок навігатора і в нього додаються нові елементи, і нарешті, властивість ShowHint встановлюється в true.

"Нові" Характеристики компонента

Коли компонент поміщений на форму, з'являються тільки навігаційні кнопки і властивість ShowHint за замовчуванням встановлено в true. Новий компонент показано на рис.6.

Мал. 6. Новий компонент.

Однак, що ж станеться, якщо користувач змінить одну з цих властивостей? Чи можна це зробити під час дизайну чи виконання? Так можна. Користувач також може змінювати ці значення в Object Inspector і вони коректно будуть поводитися під час виконання. Як же так вийшло? Чи значення цих властивостей не задаються в конструкторі раз і назавжди? Відповідь до цієї головоломки криється в механізмі, який C++Builderвикористовує для побудови форм. Цей приклад трохи спрощений, але досить точний для ілюстрації механізму.

Спочатку C++Builder викликає конструктор форми. У цей момент він відкриває DFM файл (який у цей час вже вбудований у виконуваний), зчитує імена компонентів та конструює їх один за одним. Однак він ігнорує значення властивостей з DFM файлу. Порядок, в якому конструюються компоненти, такий самий, як вони йдуть у файлі DFM. Далі, коли конструктор форми завершується, відбувається повернення до DFM і починається привласнення значень всім властивостям компонент.

Зауважте, що C++Builder завжди конструює компоненти зі значеннями за умовчанням, і лише потім надає значення з DFM. Це також пояснює, чому наш компонент працює правильно - навіть якщо в конструкторі задаються нові значення, вони потім будуть перекриті значеннями з форми.

Ця техніка також працює із компонентами баз даних. Наприклад, якщо кожен новий проект використовує ті самі установки з'єднання з БД, було б легко і зручно створити новий змінений компонент Database з уже встановленими характеристиками. Це також вірно для таблиць або запитів, які також часто використовуються повторно.

Можна також скористатися ще кількома перевагами такої архітектури. Наприклад, можна перевизначити метод Loaded компонента. Форма автоматично викликає його, коли закінчує завантаження та привласнення даних із DFM. Це означає, що в ньому можна вжити деяких додаткових дій.

Коли компонент встановлюється, йому призначається іконка(бітмап) його найближчого предка або бітмап за замовчуванням. Можна створити оригінальний біт-мап для компонента.

Бітмапи, які видно на палітрі, не компілюються в компонент, оскільки вони потрібнілише під час проектування. Натомість вони повинні бути у файлах з розширенням .DCR (Dynamic Component Resource) та ім'ям, що збігається з ім'ям модуля компонента. Цю вимогу необхідно дотримуватись - якщо ім'я буде відрізнятися, бітмап не завантажиться. C++Builder надає засіб Image Editor до створення бітмапів (див. рис.7). За допомогою нього можна створити новий файл DCR.

бібліотек

Мал. 7. Image Editor.

Щоб створити новий бітмап для компонента, розробник повинен клацнути правою клавішею та вибрати відповідний пункт меню. З'явиться діалог Bitmap Properties, показаний на рис. 8. Бітмап повинен бути квадратом 24x24 пікселів і мати палітру VGA (16 colors).

пакетних

Мал. 8. Діалог Bitmap Properties.

Щоб розпочати редагування біт-мапу, потрібно вибрати відповідний пункт меню. З'явиться палітра редагування біт-мапу, показана на рис.9.

створення

Мал. 9. Палітра редагування растрових зображень.

Мал. 10. TDefaultedDBNavigator та його бітмап.

C++Builder дозволяє налагоджувати і пакеджі, і DLL. Насправді процес їх налагодження однаковий, тому що в загальній частині вони одне і те ж.

пакетних

Мал. 11. Завдання хост-процесу.

Використання C++Builder IDE як хост-процес для пакеджа

Так як пакедж - це DLL, ви можете налагоджувати його так само. Ви відкриваєте проект пакеджа в C++Builder IDE, вибираєте Run Parameters з меню та задаєте ім'я хост-процесу. А тепер простий трюк – якщо ви хочете налагоджувати пакедж дизайну, просто задайте BCB.EXE як хост-процес, от і все. Введіть повний шлях до BCB.EXE та його ім'я в полі Host Application.

Після того, як ви поставите BCB.EXE як хост-процес, виберіть Run Run або натисніть F9 для початкуналагодження пакеджу. C++Builder створить інший екземпляр C++Builder, який виступає як запускаючий процес. Ця друга копія та завантажить ваш пакедж дизайну. Поверніться до першої копії, розставте точки зупинки. Потім знову перейдіть до другої копії та маніпулюйте нею, щоб досягти цих точок.

Зауваження та пропозиції

Примітка 2:Під час налагодження може з'явитися винятокEResNotFound, що повідомляє "Resource DBXDBI not found.". Джерело його до кінця не зрозуміле, але його можна просто ігнорувати.

Примітка 3:Зберігайте, перш ніж почати налагоджуватися :))

Примітка 4:Ця техніка чудово працює з пакеджами, які підключаються до IDE за допомогою OpenTools IDE.

Примітка 5:Постарайтеся налагодитись у Windows NT, якщо це можливо. Якщо щось впаде, так буде набагато легше відновитись.

Примітка 6:Ви можете вказати параметр командного рядка-nsдля другої копії C++Builder, щоб під час її запуску не показувалося зображення.

Примітка 7:Компіляція проекту з другої копії C++Builder може взагалі не працювати, оскільки вона, швидше за все, запускається з папки, де знаходиться проект пакеджу.