- •В.В. Чуркин
- •Содержание
- •Ознакомление с Интегрированной Средой Разработки (иср)
- •Основное окно иср
- •Библиографический список
- •Занятие 1 Формы и компоненты Включение в проект новой формы
- •Размещение компонентов на форме
- •Депозитарий – хранилище форм и проектов
- •Задание 7. Опробовать режимы заимствования форм из Депозитария
- •Контрольные вопросы
- •Библиографический список
- •Занятие 2 Отладка приложений Компиляция и компоновка проекта
- •Сообщения компилятора и компоновщика
- •Действия в случае ошибки выполнения
- •Дальнейшие действия
- •Окно наблюдения Список Часов
- •Окно оценки и модификации Оценить|Изменить
- •Пошаговое выполнение приложения
- •Точки прерывания
- •Использование окна Инспектора Отладки
- •Другие средства отладки
- •Контрольные вопросы
- •Библиографический список
- •Занятие 3 Компоненты ввода и отображения текстовой информации
- •Компоненты Label, StaticText, Panel
- •Компоненты Edit, LabeledEdit, MaskEdit
- •Компоненты Memo, RichEdit
- •Компоненты ListBox, CheckListBox, ValueListEditor
- •Компонент StringGrid
- •Контрольные вопросы
- •Библиографический список
- •Занятие 4 Диаграммы и графики Компонент Chart
- •Компонент Image
- •Контрольные вопросы
- •Библиографический список
- •Контрольные вопросы
- •Библиографический список
- •Формирование квадратных матриц
- •Контрольные вопросы
- •Библиографический список
- •Кнопки, индикаторы, управляющие элементы
- •Управляющие кнопки Button и BitBtn
- •Кнопка с фиксацией SpeedButton
- •Группы радиокнопок − компоненты RadioGroup, RadioButton и GroupBox
- •Индикаторы CheckBox и CheckListBox
- •Ползунки и полосы прокрутки − компоненты TrackBar и ScrollBar
- •Заголовки − компоненты HeaderControl и Header
- •Таймер − компонент Timer
- •Календарь − компонент DateTimePicker
- •Панели и компоненты внешнего оформления
- •Панели общего назначения − компоненты Panel,
- •Многостраничные панели − компоненты TabControl,
- •Инструментальные панели − компоненты ToolBar и PageScroller
- •Перестраиваемые панели − компоненты CoolBar и ControlBar
- •Контрольные вопросы
- •Библиографический список
- •Занятие 8 Системные диалоги
- •Диалоги открытия и сохранения файлов – компоненты
- •Фрагменты диалогов – компоненты
- •Диалог выбора шрифта – компонент FontDialog
- •Диалоги выбора цвета – компоненты ColorDialog, ColorBox
- •Контрольные вопросы
- •Библиографический список
- •Занятие 9 Технология разработки приложений. Диспетчеризация действий
- •Диспетчеризация действий на основе компонента ActionList
- •Диспетчеризация действий на основе компонентов ActionManager, ActionMainMenuBar, ActionToolBar, CustomizeDlg
- •Контрольные вопросы
- •Библиографический список
- •Занятие 10 Динамически присоединяемые библиотеки dll Назначение dll
- •Статическое и динамическое связывание dll с приложением
- •Создание dll
- •Примеры статического и динамического связывания dll
- •Контрольные вопросы
- •Библиографический список
Примеры статического и динамического связывания dll
Продолжим работу с DLL и напишем тестирующее приложение. Чтобы более гибко переключаться между отлаживаемой библиотекой и кодом теста, объединим с помощью Менеджера проекта модуль DLL и тестирующий проект в одну группу. Сначала рассмотрим реализацию статического связывания.
Выполним команду Вид/Менеджер проекта. Откроется окно Менеджера проекта с одной вершиной MyDLL.dll. Развернем её (рис.10.5) и снова свернем.
Рис.10.5 – окно Менеджера проекта с загруженной DLL
Рис.10.6 – в окне Менеджера проекта появилась новая вершина
В окне Менеджера проекта нажмем кнопку Новый и в окне Новые элементы на странице Новый выберем пиктограмму Приложение. Нажмем ОК. На экране появится пустая форма. Выполним команду Вид/Менеджер проекта и увидим, что в окне Менеджера проекта появилась вершина Project1.exe, соответствующая создаваемому тестовому приложению (рис.10.6).
Выполним команду Файл/Сохранить проект как и сохраним модуль тестового приложения под именем UTestDLL, а проект – под именем PTestDLL.
Рис.10.7 – окно Менеджера проекта с загруженной DLL и тестом
Введем команду Файл/Сохранить все и сохраним проект под именем TESTDLL. Снова выполним команду Вид/Менеджер проекта и в окне Менеджера проекта увидим загруженную DLL и вершину PTestDLL.exe, соответствующую создаваемому тестовому приложению (рис.10.7).
Разместим на форме окно редактирования Edit1 и кнопку Button1 (рис.10.8).
а) б)
Рис.10.8 – тестовое приложение DLL: исходный текст в окне (а)
и результат кодировки (б)
В модуле приложения в обработчик щелчка на кнопке поместим оператор:
Edit1->Text = Code_Dec(Edit1->Text.c_str(),’A’);
Он берет текст, занесенный пользователем в окно редактирования Edit1, кодирует его с помощью функции Code_Dec и возвращает закодированную строку в Edit1.
Включим в модуль приложения после директивы препроцессора #pragma hdrstop директиву, подключающую заголовочный файл библиотеки:
#include “UMyDLL.h”
Приведем заголовочный файл модуля UTestDLL.h:
//---------------------------------------------------------------------------
#ifndef UTestDLLH
#define UTestDLLH
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm1 : public TForm
{
__published: // IDE-managed Components
TEdit *Edit1;
TButton *Button1;
void __fastcall Button1Click(Tobject *Sender);
private: // User declarations
public: // User declarations
__fastcall TForm1(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm1 *Form1;
//---------------------------------------------------------------------------
#endif
и файл реализации модуля UTestDLL.cpp:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
#include “UMyDLL.h”
#include “UTestDLL.h”
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource “*.dfm”
TForm1 *Form1;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(Tcomponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(Tobject *Sender)
{
Edit1->Text = Code_Dec(Edit1->Text.c_str(),’A’);
}
//---------------------------------------------------------------------------
Осталось подключить к тестирующему приложению файл .lib, обеспечивающий статическое связывание библиотеки. Для этого сначала нужно активизировать приложение в окне Менеджера проекта, выделив вершину проекта PTestDLL.exe и нажав на кнопку Активизировать (рис.10.9).
Рис.10.9 – подготовка к активизированию приложения
Введём команду Проект/Добавить к проекту… . Во всплывшем диалоговом окне выберем шаблон файлов «Файл библиотеки (*.lib)» и выберем файл MyDLL.lib. Файл библиотеки окажется включенным в тестирующее приложение (рис.10.10). Это обеспечит при запуске приложения статическое связывание библиотеки.
Теперь можно сохранить проект, откомпилировать и выполнить его. Результаты работы приложения показаны на рис.10.8.
Рис.10.10 – файл библиотеки включен в тестирующее приложение
Перейдем к рассмотрению варианта динамического связывания. В окне Менеджера проекта нажмем кнопку Новый и в окне Новые элементы на странице Новый выберем пиктограмму Приложение. Нажмем ОК. На экране появится пустая форма.
Выполним команду Файл/Сохранить проект как и сохраним (в том же каталоге, где находится DLL) модуль под именем UTestDLL2, а проект – под именем PTestDLL2. С помощью окна Менеджера проекта убедимся, что второе тестирующее приложение добавлено (рис.10.11).
Рис.10.11 - окно Менеджера проекта с загруженной DLL,
первым тестом PTestDLL.exe и вторым тестом PTestDLL2.exe
Рис.10.12 – тестовое приложение динамического связывания DLL
Разместим на форме окно редактирования Edit1 и три кнопки Button1,2,3 (рис.10.12). Кнопка Загрузить (имя BLoad) будет обеспечивать загрузку DLL, кнопка Выгрузить (имя BFree) будет выгружать библиотеку из памяти, а кнопка Кодировать/Декодировать (имя Button1) аналогична той, которая была в первом приложении.
В заголовочном файле второго приложения в описание класса формы нужно внести объявления (см. ниже).
//---------------------------------------------------------------------------
#ifndef UTestDLL2H
#define UTestDLL2H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
//---------------------------------------------------------------------------
class TForm2 : public TForm
{
__published: // IDE-managed Components
TEdit *Edit1;
TButton *Button1;
TButton *BLoad;
TButton *BFree;
void __fastcall BLoadClick(TObject *Sender);
void __fastcall BFreeClick(TObject *Sender);
void __fastcall Button1Click(TObject *Sender);
private: // User declarations
// Объявление указателя на DLL
HINSTANCE dllInstance;
// Объявление указателя на функцию
typedef char* (__import FType(char *, char));
FType * C_D;
public: // User declarations
__fastcall TForm2(TComponent* Owner);
};
//---------------------------------------------------------------------------
extern PACKAGE TForm2 *Form2;
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
Переменная dllInstance будет содержать указатель на загруженный модуль DLL. Вводимый тип FType соответствует типу функции Code_Dec, которая будет вызвана из библиотеки. А переменная C_D будет содержать указатель на эту функцию.
Приведем файл реализации модуля формы второго приложения:
#include <vcl.h>
#pragma hdrstop
#include "UTestDLL2.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TForm2 *Form2;
//---------------------------------------------------------------------------
__fastcall TForm2::TForm2(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm2::BLoadClick(TObject *Sender)
{
// Загрузка DLL
dllInstance = LoadLibrary("MyDLL.dll");
if(dllInstance)
// получение указателя на функцию
C_D = (FType *)GetProcAddress(dllInstance, "_Code_Dec");
else ShowMessage(«Не удалось загрузить 'MyDLL.dll'»);
}
//---------------------------------------------------------------------------
void __fastcall TForm2::BFreeClick(TObject *Sender)
{
// выгрузка DLL
FreeLibrary(dllInstance);
C_D = NULL;
}
//---------------------------------------------------------------------------
void __fastcall TForm2::Button1Click(TObject *Sender)
{
if (C_D)
Edit1->Text = C_D(Edit1->Text.c_str(),'A');
else ShowMessage(
" Функция 'Code_Dec' из 'MyDLL.dll' недоступна");
}
//---------------------------------------------------------------------------
Обработчик BLoadClick загружает библиотеку функцией LoadLibrary. Если загрузить библиотеку не удалось, то значение dllInstance окажется равным NULL. В этом случае пользователю выдается сообщение «Не удалось загрузить 'MyDLL.dll'». А если загрузка прошла успешно, то методом GetProcAddress в переменную C_D заносится указатель на импортируемую функцию.
Обработчик Button1Click обеспечивает вызов функции с помощью указателя C_D. А если указатель равен NULL (например, в библиотеке не оказалось требуемой функции, что в нашем случае невозможно, или перед выполнением Button1Click не была загружена библиотека, что в нашем случае возможно), то пользователю выдается соответствующее сообщение об ошибке.
Обработчик BFreeClick выгружает функцией FreeLibrary из памяти модуль DLL и обнуляет указатель C_D.
Выполним данное приложение и убедимся, что все работает нормально (рис.10.12).
Проведите эксперимент, размещая исполняемый файл тестового приложения и файл библиотеки в различных каталогах.