29. Из чего складывается имя событийной процедуры vb Событийная процедура
представляет собой подпрограмму, которая начинает выполняться после реализации определенного события.
Имя процедуры включает в себя имя объекта и имя события:
Объект_Событие ()
Каждая процедура представляет отдельный программный модуль, который реализует определенный алгоритм. В терминологии процедурного программирования такие процедуры соответствуют подпрограммам, поэтому каждая из событийных процедур начинается с ключевого слова Sub(subroutine — подпрограмма) и заканчивается ключевыми словами End Sub
30. Какое число символов может содержать имя переменной vb
Использованию переменной обычно предшествует ее объявление — инструкция Dim, в которой указывается как имя переменной, так и тип данных, для хранения которых она предназначена. Хотя такая инструкция и не обязательна (VBA может определять тип данных переменной по последнему символу ее имени: ! # $ % & @), тем не менее хороший стиль программирования требует предварительного описания всех используемых переменных. Имена переменных могут иметь длину до 255 символов (в том числе — символов кириллицы), и не должны содержать пробелов, знаков препинания и перечисленных выше специальных символов (за исключением последнего знака). Они не могут также совпадать с ключевыми словами VBA и именами стандартных объектов.
Чтобы выбранное имя переменной случайно не совпало с ключевым словом или названием стандартного объекта, достаточно всегда начинать имена переменных со строчной буквы (первые символы ключевых слов и имена стандартных объектов автоматически преобразуются системой программирования VBA в прописные).
В листинге 14.3 приведены примеры описания переменных различного типа с помощью инструкции Dim.
Листинг 14.3. Описание переменных
Dim a, b As Integer
Dim дата_рождения As Date
Dim Фамилия As String, Имя As String * 25
В процедурах и функциях VBA могут использоваться следующие типы данных:
О Boolean — логические переменные, принимающие одно из двух значений: ИСТИНА или ЛОЖЬ;
О Byte — целое число в диапазоне от 0 до 255;
О Currency — переменные для денежных вычислений с фиксированным количеством разрядов после десятичной запятой; позволяют избежать накопления погрешностей округления;
О Date — переменные для хранения даты и времени;
О Double — переменные для хранения значений с плавающей точкой удвоенной точности;
О Integer — целые числа в диапазоне от -32768 до 32767;
О Long— целые числа в диапазоне от -2147483648 до 2147483647;
О Object — переменные для хранения ссылок на объекты;
О Single — переменные для хранения значений одинарной точности с плавающей точкой;
О String — переменные для хранения строк длиной от 0 до 64К символов;
О Variant — переменные, тип которых определяется типом последнего значения, присвоенного им.
Кроме стандартных типов данных VBA предоставляет пользователю возможность создавать собственные типы данных (структуры) и хранить данные в массивах (группах переменных с общим именем, различаемых по сочетанию индексов). Кроме переменных, типы данных описываются для формальных параметров процедур и функций и для самих функций (тип возвращаемого функцией значения). В листинге 14.4 приведены примеры описания формальных параметров и возвращаемого значения для процедуры и функции, вычисляющих длину строки, которая получается при соединении фамилии и имени (с разделяющим их пробелом).
Событийная процедура
представляет собой подпрограмму, которая начинает выполняться после реализации определенного события.
Имя процедуры включает в себя имя объекта и имя события:
Объект_Событие ()
Каждая процедура представляет отдельный программный модуль, который реализует определенный алгоритм. В терминологии процедурного программирования такие процедуры соответствуют подпрограммам, поэтому каждая из событийных процедур начинается с ключевого слова Sub (subroutine — подпрограмма) и заканчивается ключевыми словами End Sub
События и делегаты в С# и C++
Для того, чтобы программировать, нужно знать определенные языки и их особенности. Важную роль здесь играют не только объекты и функции, но и так называемые события.
В данной статье речь зайдет о том, что такое event. Примеры будут разобраны на языках СИ-семейства – C# и C++. Это одни из самых перспективных ЯП в сфере объектно-ориентированного программирования.
Термины – базовые понятия
Перед тем, как с помощью предложенных языков писать программы и использовать обработчик событий, необходимо сначала научиться базовым приемам создания софта. А еще – запомнить несколько ключевых терминов.
Каждый разработчик должен помнить следующие определения:
- Алгоритм – набор операций и инструкций, а также указаний, с помощью которого удается решать поставленные изначально задачи.
- API — интерфейс прикладного программирования. Представлен правилами и инструкциями, помогающими создавать утилиты.
- Аргументы – значения, передаваемые в команды и функции.
- Оператор – то, что манипулирует компонентами кода через операнды.
- Операнд – объект, которым можно управлять через операторы.
- Переменная – именованная ячейка памяти, которая зарезервирована системой. Хранилище данных в программе.
- Объект – связанные между собой переменные, структурные единицы и константы, которые выбираются совместно, а также обрабатываются.
- Класс – набор связанных объектов. У них должны быть общие свойства.
- Тип данных – классификация электронных материалов определенного вида.
- Массив – множество информации. Списки и группы схожих типов данных, которые предварительно проходят стадию группировки.
- Итерация – один проход через заданный набор операций в коде.
- Ключевое слово – зарезервированное синтаксисом ЯП слово. Помогает обозначать операции и функции. Ключевое слово не может выступать в качестве имени класса, переменной или иного компонента.
- Указатели – переменные, содержащие адреса мест в памяти.
Также стоит обратить внимание на раскрытие понятия «метод». Это в объектно-ориентированном программировании – функция/процедура, которая относится к тому или иному классу, объекту. Включает в себя операторы и входные аргументы.
Событие – это…
Событие – член типа при помощи которого соответствующий тип или его экземпляр могут уведомлять иные объекты о наступлении особых ситуаций. Пример – возникновение ошибок или сбоев в системе, клик по кнопке.
Другие объекты в написанном коде при получении сообщения о событии могут давать «обратный ответ». А именно – выполнять те или иные действия. Под событием принято понимать член типа, отвечающий за обеспечение соответствующего взаимодействия компонентов в коде.
- сообщение, возникающее в различных точках исходного кода при выполнении заданных условий;
- переход объекта или класса из одного состояния в другое;
- абстракция инцидента или сигнала в реальном мире, который сигнализирует о перемещении чего-либо в новое состояние.
Отдельное внимание стоит уделить типу, в котором прописано то или иное событие. Оно должно удовлетворять некоторым «условиям».
О типах и их возможностях
Тип, в котором было определено событие, позволяет:
- Производить регистрацию обработчика событий. К ним относят статические или экземплярные методы, которые заинтересованы в получении уведомления о событии. Выполняют в ответ на event конкретные операции.
- Отменять регистрацию компонента под названием «обработчик событий».
- Уведомлять обработчик (если их несколько – все) о том, что операция произошла.
Стоит обратить внимание на то, что в C++ нет событий. При необходимости разработчику предстоит создать соответствующие «компоненты» на библиотечном уровне. Чуть позже будет рассмотрен один такой вариант, который предусматривает несколько классов. К ним относят Delegate и Event.
Делегаты
Модель event в C# базируется на делегатах. Аналогичным образом ситуация обстоит с .NET. Делегат – это тип, который содержит ссылку на метод. Он:
- объявляется при помощи сигнатуры, указывающий тип возвращаемого значения и параметры для методов, на которые происходит ссылка;
- способен включать в себя лишь ссылки на методы, соответствующие сигнатуре;
- эквивалентен указателю на строго типизированные функции или обратные вызовы.
Для того, чтобы объявить делегат, достаточно определить его класс. В .NET соответствующий компонент имеет широкую область применения, как и в C#.
Вот пример объявления делегата в C#:
Public delegate void ThresholdReachedEventHander(object sender, ThresholdReachedEventArgs e);
Стоит обратить внимание на то, что сценарии, для которых требуется определять собственные делегаты, встречаются на практике крайне редко. Пример – когда ведется работа с кодом, не умеющим распознавать универсальные типы.
События – ключевые моменты
Стоит обратить внимание на то, как правильно осуществлять работу с events. Далее будет представлена информация, помогающая обрабатывать «сообщения системы», объявлять их и корректировать при необходимости.
Определение и вызов
События в классе будут объявляться при помощи ключевого слова – event. После него требуется указать тип делегата, который представляет «происшествие».
- Есть public class.
- В самом начале осуществляется определение делегата AccountHandler. Он будет принимать один параметр вида string.
- При помощи ключевого слова происходит создание некоторого event с именем Notify. Оно представляет delegate.
- Название события может выступать в качестве произвольного. Оно обязательно представляет тот или иной делегат.
После того, как событие оказалось определено, можно его вызвать как метод. Для этого необходимо использовать имя события. Чтобы избежать ошибок в момент, когда осуществляется обработка «сообщения», стоит проверять его на null:
Можно вызвать event через метод Invoke(). Для этого предстоит передать в него желаемые значения для параметров.
А вот программа, которая послужит примером реализации рассмотренных операций:
Система здесь получит уведомление о том, что средства добавлены/сняты со счета. Также система выдаст сообщение, если на балансе недостаточно денег.
Как добавить обработчик
В программировании можно добавлять один или несколько обработчиков. Это – то, что будет выполняться при вызове «происшествия». Часто это не классы, а методы. Каждый обработчик событий по списку заданных параметров и возвращаемому типу будет соответствовать делегату, которые представляет событие. Для того, чтобы добавить обработчик, нужно применить операцию «+=».
- Используется метод DisplayMessage. Он соответствует delegate AccountHandler.
- При вызове данных события будет обрабатываться соответствующий метод. Для параметра message передается строчка, встречающаяся в event.
- В DisplayMessage осуществляется вывод полученного сообщения. При желании можно определить здесь совершенно любую логику.
После этого можно выделить самостоятельный класс Account в качестве библиотеки классов. После – использовать в своих проектах.
Удаление
В любой момент программист может провести создание или удаление обработчиков. Для удаления необходимо использовать операцию «-=».
Выше – то, как будет выглядеть соответствующий код.
Управление
Обработка events при помощи аксессоров может управляться разработчиком. Для этого используется add или remove. Такая функциональность встречается на практике редко. Здесь можно увидеть, как происходит удаление и добавление обработчика подобным образом.
Можно также передавать некоторые данные об events. Пример – добавление в программы, указанные выше, new класс AccountEventArgs. Он будет содержать такой код:
Этот класс обладает двумя свойствами:
- Message – хранение выводимого сообщения;
- Sum – содержит сумму, на которую изменился баланс.
Теперь можно применить класс AccountEventArgs, откорректировав класс Account:
Основная программа должна выглядеть так:
Как быть с C++
Обработка events в C++ — это более сложное понятие. Связано это с тем, что обработчиков у этого языка программирования нет. Предстоит работать с различными классами. Пример – Delegate и Event.
Класс Delegate
Этот класс будет расширять понятие указателя на функцию. С его помощью удается передавать ссылки на методы объектам-делегатам. Далее последний может быть передан клиентскому коду, который косвенно вызывает метод.
Класс Delegate дает существенное преимущество – ему можно передавать динамически указатели на методы и изменять поведение приложения. Перекомпиляция здесь не нужна. Софт будет оставаться в неведении о манипуляциях.
Выше – пример использования класса Delegate.
Класс Event
Событие – способ для класса относительно оповещения клиентов о том, что что-то произошло. Можно использовать Event в C++ для реализации рассматриваемого «компонента».
В данном случае сторонний объект будет помещать указатель на свой метод в делегат. После – передавать последний событию. При срабатывании события осуществляется вызов делегата. Как следствие – метода, который ему был передан.
Выше – пример использования класса Event в C++ для обработки событий. А вот – видео-урок по рассмотренной теме в C#. Чтобы надписи типа static void, eventargs e, delegate и другие не вызывали трудности, стоит закончить специализированные дистанционные компьютерные курсы. В течение года с нуля пользователя там научат писать коды на выбранных языках. Есть как предложения для новичков, так и для опытных разработчиков.
События C# по-человечески
Невозможно, просто взять и вникнуть в этот глубокий смысл, изучая События (event) в просторах базового и, на первый взгляд, бесконечного C#.
Когда я изучал События (не в рамках .NET!), потратил много сил, чтобы, наконец-то, разобраться, как они устроены и должны конструироваться. Поэтому, я решил опубликовать свою методику понимания структуры пользовательского события, коим представляется ключевое слово event в С#.
Не буду цитировать и без того замученную MSDN, а постараюсь объяснить понятно и доступно.
- 1. Вы не должны испытывать страх перед изучением. Пожалуйста, читайте медленно и вдумчиво.
- 2. Вы должны понимать классы и методы.
- 3. Вы должны
знатьпонимать, что есть делегаты. Хотя, Вы можете попытаться понять их в ходе чтения статьи.
Итак, Событие, это ситуация, при возникновении которой, произойдут некоторые действия. Само событие имеет определенную структуру.
Предположим, что стоит такая задача: определено три класса. Первый класс будет считать до 100, используя цикл. Два других класса будут ждать, когда в первом классе счетчик досчитает, например, до 71, и после этого каждый выведет в консоль фразу «Пора действовать, ведь уже 71!». Проще говоря, при обнаружении значения 71, вызовутся по методу, соответственно для каждого класса. Разложим все по полкам.
1. Моделирование ситуации.
Подготовим эти три простейших класса, оставив точку входа в программу main нетронутой.
Класс ClassCounter и его метод Count() в котором будет производится счет. (В коде я опускаю пространства имен namespace, ибо это ясно, как день).
Два других класса (имена им Handler_I и Handler_II), которые должны реагировать на возникновение события методами public void Message(). У каждого по методу, как и договаривались.
Напомню, когда счетчик будет считать до 100 и достигнет 71, должны сработать методы Message() для классов Handler_I и Handler_II.
Теперь вернемся к классу ClassCounter и создадим счетчик при помощи цикла for c переменной-счетчиком int i.
Первый этап завершен. У нас есть класс счетчик и два класса, которые будут выводить сообщения. Условия задачи: как только i=71, должны сработать методы Message() для двух классов Handler_I и Handler_II.
2. Оформление события.
Абстрагируемся от программирования. Событие, которое мы хотим создать, будет представлять фразу «… счетчик считает. И как только он будет равен 71, должны выполниться действия». Значит, нам необходимо условие «как только он будет равен 71». Представим его при помощи условного оператора if.
Конструируем событие event. Определяем по методам, которые должны сработать при i=71 их сигнатуру (или прототип).
Сигнатура метода — это так называемая спецификация (или простыми словами «шаблон») какого-л. метода или методов. Представляет собой сочетание названия типа, который метод возвращает, плюс название типов входящих параметров (по порядку! порядок очень важен.)
Например, метод int NewMethod(int x, char y) будет иметь сигнатуру int (int, char), а метод void NewMethod() — void (void).
Как толкует MSDN, события (event) основаны на делегатах (delegate), а делегат, говоря очень простым языком — «переменная, хранящая ссылку на метод». Как Вы уже поняли, т.к. наше событие будет ссылаться на два метода void Message(), мы должны определить сигнатуру этих методов, и составить на основе этой сигнатуры делегат. Сигнатура выглядит так: void (void).
Определяем делегат (назовем его MethodContainer):
Далее, мы создаем событие при помощи ключевого слова event и связываем его с этим делегатом (MethodContainer), а, следовательно, c методами, имеющими сигнатуру void (void). Событие должно быть public, т.к. его должны использовать разные классы, которым нужно как-то отреагировать (классы Handler_I и Handler_II).
Событие имеет синтаксис: public event <НазваниеДелегата> <НазваниеСобытия>;
Название делегата — это имя делегата, на который «ссылаются» наши методы.
Теперь запустим наше событие onCount, в условии когда i=71:
Все. Событие создано. Методы, которые вызовет это событие, определены по сигнатурам и на основе их создан делегат. Событие, в свою очередь, создано на основе делегата. Пора показать событию onCount, какие же все-таки методы должны сработать (мы ведь указали только их сигнатуру).
3. Подписка.
Вернемся в точку входа программы main и создадим экземпляр класса ClassCounter. А также создадим по экземпляру классов, которые должны запуститься. (Они должны быть public).
Теперь укажем событию onCount, методы, которые должны запуститься.
Происходит это следующим образом: <КлассИлиОбъект>.<ИмяСобытия> += <КлассЧейМетодДолженЗапуститься>.<МетодПодходящийПоСигнатуре>.
Никаких скобочек после метода! Мы же не вызываем его, а просто указываем его название.
Проверка.
Теперь осталось запустить счетчик класса ClassCounter и подождать, пока i станет равным 71. Как только i=71, запустится событие onCount по делегату MethodContainer, который (в свою очередь) запустит методы Message(), которые были подписаны на событие.
Результат:
Пора действовать, ведь уже 71!
Точно, уже 71!
Заключение.
- 1. Определите условие возникновения события и методы которые должны сработать.
- 2. Определите сигнатуру этих методов и создайте делегат на основе этой сигнатуры.
- 3. Создайте общедоступное событие на основе этого делегата и вызовите, когда условие сработает.
- 4. Обязательно (где-угодно) подпишитесь на это событие теми методами, которые должны сработать и сигнатуры которых подходят к делегату.
Вы всегда можете отписаться, используя оператор «-=«: <КлассИлиОбъект>.<ИмяСобытия> -= <КлассЧейМетодДолженЗапуститься>.<МетодПодходящийПоСигнатуре>.
Преимущество Событий очевидно: классу-издателю, генерирующему событие не нужно знать, сколько классов-подписчиков подпишется или отпишется. Он создал событие для определенных методов, ограничив их делегатом по определенной сигнатуре.
События широко используются для составления собственных компонентов управления (кнопок, панелей, и т.д.).
У самых маленьких может возникнуть вопрос: что делать, если методы, которые должны сработать имеют входящий параметр (а то и не один!)?
Ответ: Все дело в делегате, на котором базируется событие. А точнее сигнатура подходящих для делегата методов. Когда Вы сконструируете делегат, «принимающий» метод с параметром, то (!) при запуске событие запросит этот параметр. Естественно, параметр может быть чем угодно.
Пару слов о .NET-событиях. Microsoft упростила задачу конструирования делегатов: .NET предлагает готовый делегат EventHandler и т.н. «пакет» входных параметров EventArgs. Желаете событие? Берете готовый EventHandler, определяетесь в параметрах, «запихиваете» их в класс, а класс наследуете от EventArgs. А дальше — как по расписанию)
Многие разработчики утверждают (и я с ними согласен), что главная проблема «недопонимания» событий — их специфическая область применения, а вследствие — мало доступных примеров. Ну и не забывайте о практике.