2006 г.
Биллиг Владимир Арнольдович
Интернет-Университет Информационных Технологий, INTUIT.ru
Назад Оглавление
Классы как обертка вызовов функций Win32 API
В предыдущих лекциях мы много говорили о классах и, в частности, рассматривали возможность применения класса в качестве упаковки тех или иных стандартных средств. Такой прием позволяет инкапсулировать в классе стандартные средства, - функции API, элементы управления, - скрыть многие детали работы с ними, а, зачастую, и предоставить конечному пользователю дополнительный сервис. Этот полезный прием целесообразно применять всякий раз, когда предполагается работа с функциями Win32 API. Все эти вопросы объявления функций, трансляции из одной формы описания в другую, описание многих параметров, не используемых по существу задачи, следует скрыть в описании класса, организовав интерфейс класса, более разумный с позиций конечного пользователя.
Каждый из наших примеров работы с функциями Win32 API достоин лучшей упаковки и представления его в виде класса. Мы ограничимся одним последним примером и представим в виде класса работу с таймером. Пожалуй, этот пример наиболее интересен, поскольку он представляет особый случай из-за наличия Callback
функции, которая, конечно же, не может быть стандартизована и должна быть задана конечным пользователем, в интересах которого и строится класс.
Построение класса "ВашТаймер"
Поскольку мы уже хорошо знакомы с тем, как строятся классы и как работать с функциями Win32 API, то нам осталось рассказать, как объединить эти две вещи в единое целое. Никаких особых деталей здесь нет. Общая стратегия такова:
- Необходимо спроектировать интерфейс класса, ориентированный на конечного пользователя. Открытые свойства и методы класса должны позволять пользователю решать все задачи, которые можно решать с помощью скрытых в классе стандартных средств.
- Встроить в класс стандартные средства, сделав их скрытыми, недоступными для внешнего использования.
- Реализовать интерфейс класса, используя встроенные средства, возможно расширив их возможности.
Применим эту общую схему для создания класса ВашТаймер
. Начнем с проектирования его интерфейса. Естественно, целью класса является предоставление пользователю возможности создавать таймер, посылающий сообщения с заданным интервалом, и удалять его, когда необходимость в нем исчезнет. Пользователь не должен ничего знать о функциях Win32 API, об операторах Declare
, преобразовании типов. Кажется естественным с этих позиций в интерфейс класса включить два метода: "СоздатьТаймер
" и "УдалитьТаймер
" и свойство "ИнтервалТаймера
", доступное для чтения и записи. Методы не имеют параметров, что облегчает работу с ними. Чтобы созданный таймер посылал сообщения с заданным интервалом, необходимо предварительно установить подходящее значение свойства, но можно этого и не делать, - в этом случае будет использоваться значение по умолчанию.
Рассматриваемый нами случай упаковки функций Win32 API особый, поскольку одна из этих функций требует вызова Callback
функции. Заметьте, функции обратного вызова не должны принадлежать упаковке, - нашему классу. Они не являются стандартными средствами, это функции, создаваемые пользователем. Поэтому они должны находиться вне модуля класса, - в стандартном классе, созданном пользователем, там, где он будет создавать и объекты класса ВашТаймер
. Чтобы не возникала соблазна поместить в класс функцию обратного вызова, такая возможность исключается синтаксически. Обратите, однако, внимание, что созданный класс предъявляет определенные требования к заголовку функции обратного вызова и даже диктует ее имя. Но обо всем по порядку и давайте вначале рассмотрим описание класса ВашТаймер
:
Пример 6: html, txt
Некоторые комментарии к этому тексту:
- О проектировании интерфейса класса мы уже говорили. Его составляют два метода, не имеющие параметров, -
СоздатьТаймер
и УдалитьТаймер
, а также процедуры - свойства Property Get
и Property Let
ИнтервалТаймера
, позволяющие взаимодействовать с закрытым свойством Интервал
. - Закрытых свойств и методов больше. Закрытыми являются операторы
Declare
, описывающие функции Win32 API SetTimer
и KillTimer
, уже упомянутое свойство Интервал
и свойство IdEv
, хранящее идентификатор таймера, о котором конечный пользователь может и не знать. - Закрытыми являются конструктор класса по умолчанию и деструктор:
Class_Initialize
и Class_Terminate
. В конструкторе инициализируется свойство Таймер
, значение которого устанавливается по умолчанию, равным одной секунде. В деструкторе класса таймер уничтожается, если он не был удален до этого. - При создании таймера устанавливается ссылка на функцию обратного вызова с именем
TimerProc
. Процедура с таким именем и уже упоминавшимися требованиями к ее заголовку должна быть описана в стандартном модуле класса, созданным конечным пользователем. - В описание класса в качестве комментария вставлена заготовка функции обратного вызова, чтобы облегчить создание этой функции конечному пользователю.
Использование класса ВашТаймер
Рассмотрим, как работать с классом ВашТаймер
. Мы не стали изобретать ничего нового, - в тестовый документ добавили две кнопки Start1
и Finish1
, которые работают также как и их тезки Start
и Finish
, но вызывают для этого методы и свойства объекта MyTimer
класса ВашТаймер
. В модуле, где объявлен соответствующий объект, находится и процедура обратного вызова TimerProc
. Вот соответствующий текст этого модуля:
Пример 6: html, txt
Комментируя этот текст, следует заметить, что введение обертывающего класса облегчает работу с таймером. Единственной проблемой остается достаточно сложное и возможно непонятное конечному пользователю описание заголовка Callback
функции TimerProc
. Чтобы облегчить ее решение, можно, как это сделано в нашем примере, заготовку этой функции включить в описание класса в качестве комментария.
В заключение приведем результаты эксперимента с нажатием кнопок Start1
и Finish1
:
Создан Таймер: Идентификатор =31711
Hi 1
Hi 2
Hi 3
Удален Таймер: Идентификатор =31711
Создан Таймер: Идентификатор =31704
Hi 4
Hi 5
Hi 6
Hi 7
Удален Таймер: Идентификатор =31704
На этом мы закончим рассмотрение темы работы с функциями Win32 API.
Назад Оглавление