- •Создание динамических структур данных
- •Встроенный динамический класс Collection
- •Создание собственных динамических классов
- •Обертывание коллекции vba
- •Несколько слов об api, Win32, dll
- •Вызов функций и оператор Declare
- •Две кодировки ansi и Unicode
- •Два языка: c и vb. Различия при вызове функций
- •Соответствие между простыми типами данных
- •Структуры языка c и тип, определенный пользователем, в языке vba
- •Об описателях языка c и объектах Windows
- •Void функции языка c
- •Вызов аргументов по ссылке ByRef и по значению ByVal
- •Строковые аргументы при вызове функций Win32 api
- •Примеры работы с Win32 api функциями
- •Работа с окнами
- •Характеристики окружения
- •Вызов функций Win32 api, работающих в Unicode кодировке
- •Обработка ошибок, возникающих при вызове функций Win32 api
- •Функции api и вызов Callback функций
- •Функции высших порядков и конструкция AddressOf
- •Функции перечисления Win32 api
- •Функция EnumWindows
- •Еще один пример работы с функцией EnumWindows
- •Функции Win32 api для работы с таймером
- •Функция SetTimer
- •Функция обратного вызова TimerProc
- •Функция KillTimer
- •Пример создания, работы и удаления таймера
- •Классы как обертка вызовов функций Win32 api
- •Построение класса "ВашТаймер"
- •Использование класса ВашТаймер
- •Операторы
- •Операторы и строки
- •Оператор комментария
- •Присваивание
- •Оператор Let
- •Оператор lSet
- •Оператор rSet
- •Оператор Set
- •Управляющие операторы
- •Условный оператор If Then Else End If
- •Оператор выбора Select Case
- •Цикл For Next
- •Цикл Do...Loop
- •Цикл While...Wend
- •Цикл For Each...Next
- •Работа с каталогами, папками и файлами
- •Изменение текущего диска: оператор ChDrive
- •Изменение текущего каталога (папки): оператор ChDir
- •Создание каталога (папки): оператор MkDir
- •Переименование каталогов (папок) и файлов: оператор Name
- •Удаление каталога (папки): оператор RmDir
- •Установка атрибутов файла: оператор SetAttr
- •Копирование файлов: оператор FileCopy
- •Удаление файлов: оператор Kill
- •Прочие операторы
- •Операции с одним объектом. Оператор With
- •Операции
- •Работа с числовыми данными
- •Математические функции
- •Работа со строками
- •Сравнение строк
- •Сравнение с образцом
- •Основные операции над строками
- •Новые функции для работы со строками
- •Функция InStrRev - поиск последнего вхождения подстроки
- •Функция Replace - замена всех вхождений подстроки
- •Удаление подстроки
- •Разбор строки. Функции Split, Join и Filter
- •Преобразование строки в массив. Функция Split
- •Сборка элементов массива в строку. Функция Join
- •Фильтрация элементов массива. Функция Filter
- •Несколько модификаций встроенных функций
- •Замена, основанная на шаблоне. Функция WildReplace
- •Замена разных символов строки. Функция CharSetReplace
- •Фильтрация, основанная на шаблоне. Функция WildFilter
- •Разбор строки, допускающей разные разделители ее элементов. Функция WildSplit
- •Работа с датами и временем
- •Присваивание значений
- •Встроенные функции для работы с датами
- •Определение текущей даты или времени.
- •Вычисления над датами
- •Функция Timer и хронометраж вычислений
- •Некоторые встроенные функции
- •Функции проверки типов данных
- •Преобразование типов данных
- •Форматирование данных. Функции группы Format
- •Функция Format.
- •Другие функции форматирования
- •Описание и создание процедур
- •Классификация процедур
- •Синтаксис процедур и функций
- •Функции с побочным эффектом
- •Создание процедуры
- •Создание процедур обработки событий
- •Вызовы процедур и функций Вызовы процедур Sub
- •Вызовы функций
- •Использование именованных аргументов
- •Аргументы, являющиеся массивами
- •Конструкция ParamArray
- •Задача о медиане
- •Пользовательские функции, принимающие сложный объект Range
- •Рекурсивные процедуры
- •Деревья поиска
- •Класс TreeNode
- •Класс BinTree
- •Работа со словарем
- •Отладка
- •Написание надежных программ
- •Искусство отладки
- •Средства отладки
- •Панель отладки и команды меню
- •Окна наблюдения
- •Окно локальных переменных - Locals
- •Окно проверки - Immediate
- •Окно контрольных выражений - Watch
Функции api и вызов Callback функций
Мы уже говорили о функциях обратного вызова, называемых Callback функциями. Для "многослойного" способа построения программных систем, характерного для программирования, функции внешнего слоя могут вызывать функции ядра без особых проблем. Однако паритета между ядром и внешним слоем нет. Вызов функций внешнего слоя из ядра затруднен. Чтобы как-то решить эту проблему и вводятся функции обратного вызова. Если функции ядра, в ответ на ее вызов из внешнего слоя, в свою очередь необходимо вызвать функцию внешнего слоя, то ядро диктует условия, каким должна удовлетворять вызываемая функция. Есть специальные механизмы, обеспечивающие вызов таких Callback функций, но во всех случаях заголовок вызываемой функции жестко фиксирован и известен ядру. Этот механизм Callback функций применяется и для обеспечения двусторонней связи между функциями VBA и функциями Win32 API, которым в процессе их работы требуется обратный вызов функций VBA.
Заметьте, в предыдущих версиях VBA не было возможности явным образом работать с функциями Win32 API, требующими вызова Callback функций. Теперь такая возможность появилась, благодаря включению в язык возможности передачи указателя функции в качестве параметра процедур и функций. Явное введение в язык конструкции AddressOf, возвращающей указатель на функцию, дало возможность при вызове функции Win32 API передать ей в качестве аргумента имя Callback функции. Попробуем разобраться в деталях того, как вызываются функции Win32 API, требующие Callback функции для своей работы, как пишутся такие функции на VBA, как передается информация между функциями, - как это все, в конечном итоге, согласуется между собой. Начнем, прежде всего, с ответа на вопрос, а как узнать, что функция Win32 API требует для своей работы вызова Callback функции. Подсказку можно получить от обозревателя, если проанализировать оператор Declare, созданный API Viewer. Когда имя параметра начинается префиксом lp, а заканчивается окончанием Func, это означает, что соответствующий аргумент является ссылкой на имя Callback функции. К сожалению, обозреватель не содержит необходимой информации о том, каким должен быть заголовок функции обратного вызова, так что необходимо обращаться к документации по Win32 API или идти на сервер. Заметьте, документация, как правило, ориентирована на C программистов, поэтому необходимо самому корректно транслировать заголовок к виду, понимаемому VBA. Ошибки в задании типов аргументов, пропуск описателя ByVal могут дорого стоить. Пожалуй, одна из наиболее сложных задач при работе с Callback функцией состоит в том, чтобы найти ее описание, а затем, используя документацию, ориентированную на язык C/C++, корректно описать на VBA заголовок этой функции.
Еще одна, важная для понимания задача состоит в организации правильного обмена информацией между процедурой VBA, вызываемой ею функцией Win32 API и вызываемой ею Callback функцией. Прежде всего, следует понимать, что программисту никогда не приходится вызывать самому Callback функцию. Ее всегда вызывает соответствующая функция Win32 API. Она же передает ей текущие значения аргументов, необходимые для работы функции обратного вызова. Но, конечно же, в большинстве случаев Callback функция производит изменения в мире объектов VBA программы и, следовательно, она должна быть каким-то образом связана с этим миром. Иногда это делается за счет того, что в функции Win32 API предусмотрен специальный параметр, который вызывающая ее программа передает ей, а она, в свою очередь, передает его функции обратного вызова. Недостаток такого способа состоит в том, что передаваемый параметр один, а информация, связывающая функцию обратного вызова с миром VBA, может быть разнородной. В этих условиях более предпочтительным может быть способ передачи и получения данных в Callback функцию через глобальные переменные. Именно этот способ мы использовали в наших примерах. Прежде, чем перейти к примерам, давайте подведем итоги и еще раз сформулируем основные этапы организации работы при вызове функций Win32 API, требующих Callback функций. Итак, необходимо:
-
Определить, что функция Win32 API требует вызова Callback функции.
-
Найти документацию по этой функции, описывающую требования к заголовку этой функции. Если эта документация ориентирована на язык C/C++, то привести ее к виду, требуемому VBA.
-
Понять, как передать информацию об объектах VBA в Callback функцию.
-
Написать одну или несколько реализаций функций обратного вызова. Обращаем внимание, что функций обратного вызова может быть несколько. Имя функции не является жестко зафиксированным. Оно передается функции Win32 API как аргумент в момент вызова. Поэтому в зависимости от контекста одну и ту же функцию Win32 API можно вызывать с различными Callback функциями.
-
Вызвать функцию Win32 API, передав ей в момент вызова имя Callback функции и другие необходимые аргументы.