Введение в события
События — это действия или случаи, возникающие в программируемой вами системе, о которых система сообщает вам для того, чтобы вы могли с ними взаимодействовать. Например, если пользователь нажимает кнопку на веб-странице, вы можете ответить на это действие, отобразив информационное окно. В этой статье мы обсудим некоторые важные концепции, связанные с событиями, и посмотрим, как они работают в браузерах. Эта статья не является исчерпывающим источником по этой теме — здесь только то, что вам нужно знать на этом этапе.
| Предпосылки: | Базовая компьютерная грамотность, базовое понимание HTML и CSS, Первые шаги в JavaScript. |
|---|---|
| Задача: | Понять фундаментальную теорию событий, как они работают в браузерах и как события могут различаться в разных средах программирования. |
Серия удачных событий
При возникновении события система генерирует сигнал, а также предоставляет механизм, с помощью которого можно автоматически предпринимать какие-либо действия (например, выполнить определённый код), когда происходит событие. Например, в аэропорту, когда взлётно-посадочная полоса свободна для взлёта самолёта, сигнал передаётся пилоту, и в результате они приступают к взлёту.

В Web события запускаются внутри окна браузера и, как правило, прикрепляются к конкретному элементу, который в нем находится. Это может быть один элемент, набор элементов, документ HTML, загруженный на текущей вкладке, или все окно браузера. Существует множество различных видов событий, которые могут произойти, например:
- Пользователь кликает мышью или наводит курсор на определённый элемент.
- Пользователь нажимает клавишу на клавиатуре.
- Пользователь изменяет размер или закрывает окно браузера.
- Завершение загрузки веб-страницы.
- Отправка данных через формы.
- Воспроизведение видео, пауза или завершение воспроизведения.
- Произошла ошибка.
Подробнее о событиях можно посмотреть в Справочнике по событиям.
Каждое доступное событие имеет обработчик событий — блок кода (обычно это функция JavaScript, вводимая вами в качестве разработчика), который будет запускаться при срабатывании события. Когда такой блок кода определён на запуск в ответ на возникновение события, мы говорим, что мы регистрируем обработчик событий. Обратите внимание, что обработчики событий иногда называют слушателями событий (от англ. event listeners). Они в значительной степени взаимозаменяемы для наших целей, хотя, строго говоря, они работают вместе. Слушатель отслеживает событие, а обработчик — это код, который запускается в ответ на событие.
Примечание: Важно отметить, что веб-события не являются частью основного языка JavaScript. Они определены как часть JavaScript-API, встроенных в браузер.
Простой пример
Рассмотрим простой пример. Вы уже видели события и обработчики событий во многих примерах в этом курсе, но давайте повторим для закрепления информации. В этом примере у нас есть кнопка , при нажатии которой цвет фона изменяется случайным образом:
button>Change colorbutton>
button margin: 10px; >
JavaScript выглядит так:
const btn = document.querySelector("button"); function random(number) return Math.floor(Math.random() * (number + 1)); > btn.onclick = function () const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; >;
В этом коде мы сохраняем ссылку на кнопку внутри переменной btn типа const , используя функцию Document.querySelector() . Мы также определяем функцию, которая возвращает случайное число. Третья часть кода — обработчик события. Переменная btn указывает на элемент — для этого типа объекта существуют возникающие при определённом взаимодействии с ним события, а значит, возможно использование обработчиков событий. Мы отслеживаем момент возникновения события при щелчке мышью, связывая свойство обработчика события onclick с анонимной функцией, генерирующей случайный цвет RGB и устанавливающей его в качестве цвета фона элемента .
Этот код теперь будет запускаться всякий раз, когда возникает событие при нажатии на элемент — всякий раз, когда пользователь щёлкает по нему.
Пример вывода выглядит следующим образом:
События не только для веб-страниц
События, как понятие, относятся не только к JavaScript — большинство языков программирования имеют модель событий, способ работы которой часто отличается от модели в JavaScript. Фактически, даже модель событий в JavaScript для веб-страниц отличается от модели событий для просто JavaScript, поскольку используются они в разных средах.
Например, Node.js — очень популярная среда исполнения JavaScript, которая позволяет разработчикам использовать JavaScript для создания сетевых и серверных приложений. Модель событий Node.js основана на том, что существуют обработчики, отслеживающие события, и эмиттеры (передатчики), которые периодически генерируют события. В общем-то, это похоже на модель событий в JavaScript для веб-страниц, но код совсем другой. В этой модели используется функция on() для регистрации обработчиков событий, и функция once() для регистрации обработчика событий, который отключается после первого срабатывания. Хорошим примером использования являются протоколы событий HTTP connect event docs.
Вы также можете использовать JavaScript для создания кросс-браузерных расширений — улучшения функциональности браузера с помощью технологии WebExtensions. В отличии от модели веб-событий здесь свойства обработчиков событий пишутся в так называемом регистре CamelCase (например, onMessage , а не onmessage ) и должны сочетаться с функцией addListener . См. runtime.onMessage page для примера.
На данном этапе обучения вам не нужно особо разбираться в различных средах программирования, однако важно понимать, что принцип работы событий в них отличается.
Способы использования веб-событий
Существует множество различных способов добавления кода обработчика событий на веб-страницы так, чтобы он срабатывал при возникновении соответствующего события. В этом разделе мы рассмотрим различные механизмы и обсудим, какие из них следует использовать.
Свойства обработчика событий
В этом курсе вы уже сталкивались со свойствами, связываемыми с алгоритмом работы обработчика событий. Вернёмся к приведённому выше примеру:
const btn = document.querySelector("button"); btn.onclick = function () var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; >;
В данной ситуации свойство onclick — это свойство обработчика события. В принципе это обычное свойство кнопки как элемента (наравне с btn.textContent или btn.style (en-US) ), но оно относится к особому типу. Если вы установите его равным какому-нибудь коду, этот код будет запущен при возникновении события (при нажатии на кнопку).
Для получения того же результата, вы также можете присвоить свойству обработчика имя уже описанной функции (как мы видели в статье Создайте свою функцию):
const btn = document.querySelector("button"); function bgChange() const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; > btn.onclick = bgChange;
Давайте теперь поэкспериментируем с другими свойствами обработчика событий.
Создайте локальную копию файла random-color-eventhandlerproperty.html и откройте её в своём браузере. Это всего лишь копия простого примера про случайные цвета, который мы уже разобрали в этой статье. Теперь попробуйте изменить btn.onclick на следующие значения и понаблюдайте за результатами:
- btn.onfocus и btn.onblur — Цвет изменится, когда кнопка будет сфокусирована или не сфокусирована (попробуйте нажать Tab, чтобы выбрать кнопку или убрать выбор). Эти свойства часто применяются для отображения информации о том, как заполнить поля формы, когда они сфокусированы, или отобразить сообщение об ошибке, если поле формы было заполнено с неправильным значением.
- btn.ondblclick (en-US) — Цвет будет изменяться только при двойном щелчке.
- window.onkeypress , window.onkeydown , window.onkeyup (en-US) — Цвет будет меняться при нажатии клавиши на клавиатуре, причём keypress ссылается на обычное нажатие (нажатие кнопки и последующее её отпускание как одно целое), в то время как keydown и keyup разделяют действия на нажатие клавиши и отпускание, и ссылаются на них соответственно. Обратите внимание, что это не работает, если вы попытаетесь зарегистрировать этот обработчик событий на самой кнопке — его нужно зарегистрировать на объекте window, который представляет все окно браузера.
- btn.onmouseover (en-US) и btn.onmouseout (en-US) — Цвет будет меняться при наведении указателя мыши на кнопку или когда указатель будет отводиться от кнопки соответственно.
Некоторые события очень общие и доступны практически в любом месте (например, обработчик onclick может быть зарегистрирован практически для любого элемента), тогда как некоторые из них более конкретны и полезны только в определённых ситуациях (например, имеет смысл использовать onplay (en-US) только для определённых элементов, таких как ).
Встроенные обработчики событий — не используйте их
Самый ранний из введённых в сеть Web методов регистрации обработчиков событий базируется на HTML атрибутах (встроенные обработчики событий):
button onclick="bgChange()">Press mebutton>
function bgChange() const rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; >
Примечание: вы можете найти полный исходник кода из этого примера на GitHub (также взгляните на его выполнение).
Значение атрибута — это буквально код JavaScript, который вы хотите запустить при возникновении события. В приведённом выше примере вызывается функция, определённая внутри элемента на той же странице, но вы также можете вставить JavaScript непосредственно внутри атрибута, например:
button onclick="alert('Hello, this is my old-fashioned event handler!');"> Press me button>
Для многих свойств обработчика событий существуют эквиваленты в виде атрибутов HTML. Однако, не рекомендуется их использовать — это считается плохой практикой. Использование атрибутов для регистрации обработчика событий кажется простым и быстрым методом, но такое описание обработчиков также скоро становится неудобным и неэффективным.
Более того, не рекомендуется смешивать HTML и JavaScript файлы, так как в дальнейшем такой код становится сложнее с точки зрения обработки (парсинга). Лучше держать весь JavaScript в одном месте. Также, если он находится в отдельном файле, вы можете применить его к нескольким документам HTML.
Даже при работе только в одном файле использование встроенных обработчиков не является хорошей идеей. Ладно, если у вас одна кнопка, но что, если у вас их 100? Вам нужно добавить в файл 100 атрибутов; обслуживание такого кода очень быстро превратится в кошмар. С помощью JavaScript вы можете легко добавить функцию обработчика событий ко всем кнопкам на странице независимо от того, сколько их было.
const buttons = document.querySelectorAll("button"); for (var i = 0; i buttons.length; i++) buttons[i].onclick = bgChange; >
Обратите внимание, что для перебора всех элементов, которые содержит объект NodeList , можно воспользоваться встроенным методом forEach() (en-US) :
.forEach(function (button) button.onclick = bgChange; >);
Примечание: Разделение логики вашей программы и вашего контента также делает ваш сайт более дружественным к поисковым системам.
Функции addEventListener() и removeEventListener()
Новый тип механизма событий определён в спецификации Document Object Model (DOM) Level 2 Events, которая предоставляет браузеру новую функцию — addEventListener() . Работает она аналогично свойствам обработчика событий, но синтаксис совсем другой. Наш пример со случайным цветом мог бы выглядеть и так:
var btn = document.querySelector("button"); function bgChange() var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; > btn.addEventListener("click", bgChange);
Примечание: вы можете найти исходный код из этого примера на GitHub (также взгляните на его выполнение).
Внутри функции addEventListener() мы указываем два параметра — имя события, для которого мы хотим зарегистрировать этот обработчик, и код, содержащий функцию обработчика, которую мы хотим запустить в ответ. Обратите внимание, что будет целесообразно поместить весь код внутри функции addEventListener() в анонимную функцию, например:
.addEventListener("click", function () var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; document.body.style.backgroundColor = rndCol; >);
Этот механизм имеет некоторые преимущества по сравнению с более старыми механизмами, рассмотренными ранее. Например, существует аналогичная функция removeEventListener() , которая удаляет ранее добавленный обработчик. Это приведёт к удалению набора обработчиков в первом блоке кода в этом разделе:
.removeEventListener("click", bgChange);
Это не важно для простых небольших программ, но для более крупных и более сложных программ он может повысить эффективность очистки старых неиспользуемых обработчиков событий. Кроме того, это позволяет вам иметь одну и ту же кнопку, выполняющую различные действия в разных обстоятельствах — все, что вам нужно сделать, это добавить/удалить обработчики событий, если это необходимо.
Также вы можете зарегистрировать несколько обработчиков для одного и того же события на элементе. Следующие два обработчика не будут применяться:
.onclick = functionA; myElement.onclick = functionB;
Поскольку вторая строка будет перезаписывать значение onclick , установленное первой. Однако, если:
.addEventListener("click", functionA); myElement.addEventListener("click", functionB);
Обе функции будут выполняться при щелчке элемента.
Кроме того, в этом механизме событий имеется ряд других мощных функций и опций. Эта тема выходит за рамки данной статьи, но если вы хотите изучить подробнее, переходите по ссылкам: Метод EventTarget.addEventListener() и Метод EventTarget.removeEventListener().
Какой механизм мне использовать?
Из трёх механизмов определённо не нужно использовать атрибуты событий HTML. Как упоминалось выше, это устаревшая и плохая практика.
Остальные два являются относительно взаимозаменяемыми, по крайней мере для простых целей
- Свойства обработчика событий имеют меньшую мощность и параметры, но лучше совместимость между браузерами (поддерживается ещё в Internet Explorer 8). Вероятно, вам следует начать с них, когда вы учитесь.
- События уровня 2 DOM ( addEventListener() и т. д.) являются более мощными, но также могут стать более сложными и хуже поддерживаться (поддерживается ещё в Internet Explorer 9). Вам также стоит поэкспериментировать с ними и стремиться использовать их там, где это возможно.
Основные преимущества третьего механизма заключаются в том, что при необходимости можно удалить код обработчика событий, используя removeEventListener() , и так же можно добавить несколько элементов-обработчиков того же типа к элементам. Например, вы можете вызвать addEventListener(‘click’, function() <. >) для элемента несколько раз, с разными функциями, указанными во втором аргументе. Это невозможно при использовании свойств обработчика событий, поскольку любые последующие попытки установить свойство будут перезаписывать более ранние, например:
.onclick = function1; element.onclick = function2; etc.
Примечание: Если вам требуется поддержка браузеров старше Internet Explorer 8 в вашем проекте, вы можете столкнуться с трудностями, так как такие старые браузеры используют старые модели событий из более новых браузеров. Но не бойтесь, большинство библиотек JavaScript (например, jQuery ) имеют встроенные функции, которые абстрагируют различия между браузерами. Не беспокойтесь об этом слишком много на этапе вашего учебного путешествия.
Другие концепции событий
Рассмотрим некоторые современные концепции, имеющие отношение к событиям. На данный момент не обязательно понимать их полностью, но представление о них поможет лучше понять некоторые модели кода, с которыми вы, вероятно, столкнётесь.
Объекты событий
Иногда внутри функции обработчика событий вы можете увидеть параметр, заданный с таким именем, как event , evt или просто e . Называется он объектом события и он автоматически передаётся обработчикам событий для предоставления дополнительных функций и информации. Например, давайте немного перепишем наш пример со случайным цветом:
function bgChange(e) var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; e.target.style.backgroundColor = rndCol; console.log(e); > btn.addEventListener("click", bgChange);
Примечание: вы можете найти исходник кода для этого примера на GitHub (также взгляните на его выполнение).
Итак в коде выше мы включаем объект события e в функцию, а в функции — настройку стиля фона для e.target , который является кнопкой. Свойство объекта события target всегда является ссылкой на элемент, с которым только что произошло событие. Поэтому в этом примере мы устанавливаем случайный цвет фона на кнопке, а не на странице.
Примечание: Вместо e / evt / event можно использовать любое имя для объекта события, которое затем можно использовать для ссылки на него в функции обработчика событий. e / evt / event чаще всего используются разработчиками, потому что они короткие и легко запоминаются. И хорошо придерживаться стандарта.
e.target применяют, когда нужно установить один и тот же обработчик событий на несколько элементов и, когда на них происходит событие, применить определённое действие к ним ко всем. Например, у вас может быть набор из 16 плиток, которые исчезают при нажатии. Полезно всегда иметь возможность просто указать, чтобы объект исчез, как e.target , вместо того, чтобы выбирать его более сложным способом. В следующем примере (см. исходный код на useful-eventtarget.html,а как он работает можно посмотреть здесь), мы создаём 16 элементов с использованием JavaScript. Затем мы выберем все из них, используя document.querySelectorAll() , и с помощью цикла for выберем каждый из них, добавив обработчик onclick к каждому так, чтобы случайный цвет применялся к каждому клику:
var divs = document.querySelectorAll("div"); for (var i = 0; i divs.length; i++) divs[i].onclick = function (e) e.target.style.backgroundColor = bgChange(); >; >
Результат выглядит следующим образом (попробуйте щёлкнуть по нему):
doctype html> html> head> meta charset="utf-8" /> title>Useful event target exampletitle> style> div background-color: #ff6600; height: 100px; width: 25%; float: left; > style> head> body> script> for (var i = 1; i 16; i++) var myDiv = document.createElement("div"); document.body.appendChild(myDiv); > function random(number) return Math.floor(Math.random() * number); > function bgChange() var rndCol = "rgb(" + random(255) + "," + random(255) + "," + random(255) + ")"; return rndCol; > var divs = document.querySelectorAll("div"); for (var i = 0; i divs.length; i++) divs[i].onclick = function (e) e.target.style.backgroundColor = bgChange(); >; > script> body> html>
Большинство обработчиков событий, с которыми вы столкнулись, имеют только стандартный набор свойств и функций (методов), доступных для объекта события (см. Event для ссылки на полный список). Однако некоторые более продвинутые обработчики добавляют специальные свойства, содержащие дополнительные данные, которые им необходимо выполнять. Например, Media Recorder API (en-US) имеет событие, доступное для данных, которое срабатывает, когда записано какое-либо аудио или видео и доступно для выполнения чего-либо (например, для сохранения или воспроизведения). Соответствующий объект события ondataavailable handler имеет свойство данных, содержащее записанные аудио- или видеоданные, чтобы вы могли получить к нему доступ и что-то сделать с ним.
Предотвращение поведения по умолчанию
Иногда бывают ситуации, когда нужно остановить событие, выполняющее то, что оно делает по умолчанию. Наиболее распространённым примером является веб-форма, например, пользовательская форма регистрации. Когда вы вводите данные и нажимаете кнопку отправки, естественное поведение заключается в том, что данные должны быть отправлены на указанную страницу на сервере для обработки, а браузер перенаправляется на страницу с сообщением об успехе (или остаться на той же странице, если другое не указано).
Но если пользователь отправил данные не правильно, как разработчик, вы хотите остановить отправку на сервер и выдать сообщение об ошибке с информацией о том, что не так и что нужно сделать. Некоторые браузеры поддерживают функции автоматической проверки данных формы, но, поскольку многие этого не делают, вам не следует полагаться на них и выполнять свои собственные проверки валидации. Давайте посмотрим на простой пример.
Простая форма HTML, в которой требуется ввести ваше имя и фамилию:
form> div> label for="fname">Имя: label> input id="fname" type="text" /> div> div> label for="lname">Фамилия: label> input id="lname" type="text" /> div> div> input id="submit" type="submit" /> div> form> p>p>
div margin-bottom: 10px; >
В JavaScript мы реализуем очень простую проверку внутри обработчика события onsubmit (событие «отправить» запускается в форме, когда оно отправлено), который проверяет, пусты ли текстовые поля. Если они пусты, мы вызываем функцию preventDefault() объекта события, которая останавливает отправку формы, а затем выводит сообщение об ошибке в абзаце ниже нашей формы, чтобы сообщить пользователю, что не так:
var form = document.querySelector("form"); var fname = document.getElementById("fname"); var lname = document.getElementById("lname"); var submit = document.getElementById("submit"); var para = document.querySelector("p"); form.onsubmit = function (e) if (fname.value === "" || lname.value === "") e.preventDefault(); para.textContent = "Оба поля должны быть заполнены!"; > >;
Очевидно, что это довольно слабая проверка формы — это не помешает пользователю отправить форму с пробелами или цифрами, введёнными в поля, но для примера подходит. Вывод выглядит следующим образом:
Примечание: чтобы увидеть исходный код, откройте preventdefault-validation.html (также запустите здесь).
Всплытие и перехват событий
Последним предметом для рассмотрения в этой теме является то, с чем вы не часто будете сталкиваться, но это может стать настоящей головной болью, если вы не поймёте, как работает следующий механизм. Всплытие и перехват событий — два механизма, описывающих, что происходит, когда два обработчика одного и того же события активируются на одном элементе. Посмотрим на пример. Чтобы сделать это проще — откройте пример show-video-box.html в одной вкладке и исходный код в другой вкладке. Он также представлен ниже:
doctype html> html> head> meta charset="utf-8" /> title>Show video box exampletitle> style> div position: absolute; top: 50%; transform: translate(-50%, -50%); width: 550px; height: 420px; border-radius: 10px; background-color: #eee; background-image: linear-gradient( to bottom, rgba(0, 0, 0, 0.1), rgba(0, 0, 0, 0.4) ); > .hidden left: -50%; > .showing left: 50%; > div video display: block; width: 400px; margin: 50px auto; > style> head> body> button>Display videobutton> div class="hidden"> video> source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.mp4" type="video/mp4" /> source src="https://raw.githubusercontent.com/mdn/learning-area/master/javascript/building-blocks/events/rabbit320.webm" type="video/webm" /> p> Your browser doesn't support HTML5 video. Here is a a href="rabbit320.mp4">link to the videoa> instead. p> video> div> script> var btn = document.querySelector("button"); var videoBox = document.querySelector("div"); var video = document.querySelector("video"); btn.onclick = function () displayVideo(); >; function displayVideo() if (videoBox.getAttribute("class") === "hidden") videoBox.setAttribute("class", "showing"); > > videoBox.addEventListener("click", function () videoBox.setAttribute("class", "hidden"); >); video.addEventListener("click", function () video.play(); >); script> body> html>
Это довольно простой пример, который показывает и скрывает с элементом внутри него:
button>Display videobutton> div class="hidden"> video> source src="rabbit320.mp4" type="video/mp4" /> source src="rabbit320.webm" type="video/webm" /> p> Your browser doesn't support HTML5 video. Here is a a href="rabbit320.mp4">link to the videoa> instead. p> video> div>
div position: absolute; top: 50%; transform: translate(-50%,-50%); . > .hidden left: -50%; > .showing left: 50%; >
var btn = document.querySelector("button"); btn.onclick = function () videoBox.setAttribute("class", "showing"); >;
Затем мы добавляем ещё пару обработчиков событий onclick. Первый к , а второй к . Идея заключается в том, чтобы при щелчке по области вне зоны видео поле снова скрылось, а при клике в области видео начало воспроизводиться.
var videoBox = document.querySelector("div"); var video = document.querySelector("video"); videoBox.onclick = function () videoBox.setAttribute("class", "hidden"); >; video.onclick = function () video.play(); >;
Но есть проблема: когда вы нажимаете на видео, оно начинает воспроизводиться, но одновременно вызывает скрытие . Это связано с тем, что видео находится внутри , это часть его, поэтому нажатие на видео фактически запускает оба вышеуказанных обработчика событий.
Всплытие и перехват событий — концепция выполнения
На стадии захвата происходит следующее:
- Браузер проверяет, имеет ли самый внешний элемент ( ) обработчик события onclick , зарегистрированный на нем на этапе захвата и запускает его, если это так.
- Затем он переходит к следующему элементу внутри и выполняет то же самое, затем следующее и так далее, пока не достигнет элемента, на который на самом деле нажали.
На стадии всплытия происходит полная противоположность:
- Браузер проверяет, имеет ли элемент, который был фактически нажат, обработчик события onclick , зарегистрированный на нем в фазе всплытия, и запускает его, если это так.
- Затем он переходит к следующему непосредственному родительскому элементу и выполняет то же самое, затем следующее и так далее, пока не достигнет элемента .

(Нажмите на изображение, чтобы увеличить диаграмму)
В современных браузерах по умолчанию все обработчики событий регистрируются в фазе всплытия. Итак, в нашем текущем примере, когда вы нажимаете видео, событие click вызывается из элемента наружу, в элемент . По пути:
- Он находит обработчик video.onclick. и запускает его, поэтому видео сначала начинает воспроизводиться.
- Затем он находит обработчик videoBox.onclick. и запускает его, поэтому видео также скрывается.
Исправление проблемы с помощью stopPropagation()
Чтобы исправить это раздражающее поведение, стандартный объект события имеет функцию, называемую stopPropagation() , которая при вызове в обработчике событий объекта делает так, чтобы обработчик выполнялся, но событие не всплывало дальше по цепочке, поэтому не будут запускаться другие обработчики.
Поэтому мы можем исправить нашу текущую проблему, изменив вторую функцию-обработчик в предыдущем блоке кода:
.onclick = function (e) e.stopPropagation(); video.play(); >;
Вы можете попробовать создать локальную копию show-video-box.html и попробовать его самостоятельно исправить или просмотреть исправленный результат в show-video-box-fixed.html (также см. исходный код здесь).
Примечание: Зачем беспокоиться как с захватом, так и с всплыванием? Что ж, в старые добрые времена, когда браузеры были менее совместимы, чем сейчас, Netscape использовал только захват событий, а Internet Explorer использовал только всплывающие события. Когда W3C решил попытаться стандартизировать поведение и достичь консенсуса, они в итоге получили эту систему, которая включала в себя и то, и другое, что реализовано в одном из современных браузеров.
Примечание: Как упоминалось выше, по умолчанию все обработчики событий регистрируются в фазе всплытия и это имеет смысл в большинстве случаев. Если вы действительно хотите зарегистрировать событие в фазе захвата, вы можете сделать это, зарегистрировав обработчик с помощью addEventListener() и установив для третьего дополнительного свойства значение true .
Делегирование события
Всплытие также позволяет нам использовать делегирование событий. Если у какого-либо родительского элемента есть множество дочерних элементов, и вы хотите, чтобы определённый код выполнялся при щелчке (событии) на каждом из дочерних элементов, можно установить обработчик событий на родительском элементе и события, происходящие на дочерних элементах будут всплывать до их родителя. При этом не нужно устанавливать обработчик событий на каждом дочернем элементе.
-
и он будет всплывать в элементах списка.
Эту концепцию объясняет в своём блоге Дэвид Уолш, где приводит несколько примеров. (см. How JavaScript Event Delegation Works.)
Вывод
Это все, что вам нужно знать о веб-событиях на этом этапе. Как уже упоминалось, события не являются частью основного JavaScript — они определены в веб-интерфейсах браузера (Web API).
Кроме того, важно понимать, что различные контексты, в которых используется JavaScript, обычно имеют разные модели событий — от веб-API до других областей, таких как браузерные WebExtensions и Node.js (серверный JavaScript). Может сейчас вы не особо в этом разбираетесь, но по мере изучения веб-разработки начнёт приходить более ясное понимание тематики.
Если у вас возникли вопросы, попробуйте прочесть статью снова или обратитесь за помощью к нам.
Смотрите также
- Event order (обсуждение захвата и всплытий) — превосходно детализированная часть от Peter-Paul Koch.
- Event accessing (discussing of the event object) — another excellently detailed piece by Peter-Paul Koch.
- Event reference
- Назад
- Обзор: Building blocks
- Далее
В этом модуле
- Принятие решений в вашем коде — условные конструкции
- Зацикливание кода
- Функции — Переиспользуемые блоки кода
- Создайте свою собственную функцию
- Возвращаемое значение функции
- Введение в события
- Создание галереи
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 3 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
§ 3. Проектирование интерфейса оконного приложения с использованием элементов управления
Элементами управления называются объекты, которые используются для отображения данных или выполнения операций с данными. Действия с элементами управления можно осуществлять с помощью мыши или клавиатуры. Управление различными программами более или менее единообразно, потому что в составе ОС имеется набор элементов управления: типовых кнопок, редактируемых полей, списков выбора, флажков, переключателей и т. д. Все элементы управления собраны в специальные библиотеки компонентов. Среда разработки программ Delphi использует библиотеку VCL (Visual Component Library) — библиотеку визуальных компонентов.
Компоненты библиотеки VCL размещаются на различных страницах палитры компонентов (пример 2.7.). Каждая страница имеет свое название. На страницах Standard (пример 3.1.) и Additional (пример 3.2.) размещены наиболее употребляемые компоненты.
Расположение компонентов по страницам палитры компонентов запоминать необязательно. Можно воспользоваться поиском (пример 3.3.).
Каждому элементу управления в среде Delphi соответствует один или несколько компонентов.
Пример 3.1. Палитра компонентов Standard:

Пример 3. 2. Палитра компонентов Additional:

Пример 3.3. Поиск компонента Button:
3.2. Элемент управления Button (кнопка)

Компонент Button (кнопка) относится к элементам управления. На панели компонентов Standard кнопка изображена в виде , имя объекта — Button. Кнопка, помещенная на форму, получает имя ButtonN, где N — номер 1, 2, 3… (пример 3.4). При необходимости кнопку можно переместить в любое место формы. Ключевые точки позволят установить нужный размер кнопки.
Некоторые свойства компонента Button перечислены в таблице (пример 3.5).
Как видно из таблицы, многие свойства кнопки совпадают по именам и назначениям со свойствами формы, поэтому в дальнейшем для компонентов будут указываться только те свойства, которые отличны от уже описанных для других компонентов.
Основным событием компонента Button является OnClick. Для создания обработчика события OnClick для кнопки можно поступить так же, как и при создании аналогичного обработчика для формы: выбрать событие на вкладке Events и выполнить двойной щелчок в поле напротив события OnClick. Можно просто выполнить двойной щелчок по кнопке. (Для формы основным событием является событие OnCreate, поэтому при двойном щелчке по форме создается обработчик события OnCreate)
Пример 3.6. Создать проект, разместив на форме две кнопки. При нажатии на одну из них цвет формы должен измениться на синий, а при нажатии на вторую — должен восстановиться исходный цвет.
Этапы выполнения задания
- Поместить на форму две кнопки.
- Изменить свойство Caption у кнопки Button1 на Изменить цвет.
- Изменить свойство Caption у кнопки Button2 на Восстановить цвет.
- Создать обработчик события OnClik для кнопки Button1 и изменить цвет формы. Команда
Form1.Color := clBlue; - Создать обработчик события OnClik для кнопки Button2 и изменить цвет формы на первоначальный (название цвета формы указано в поле Color инспектора объектов). Команда
Form1.Color := clBtnFace; - Сохранить изменения в проекте.
Пример 3.4. Компонент Button на форме:

Пример 3.5. Свойства компонента Button.
Свойство
Назначение
Заголовок (внешнее имя) кнопки, текст, который отображается на кнопке. По умолчанию — Button1

Свойства шрифта для подписи заголовка. Свойство Font является сложным, о чем свидетельствует значок . При нажатии на этот значок раскрываются все свойства шрифта. Нажатие на кнопку вызовет стандартное окно установки свойств шрифта
Горизонтальная координата положения верхнего левого угла кнопки на форме
Вертикальная координата положения верхнего левого угла кнопки на форме
Имя (внутреннее) кнопки. Используется в программном коде для обращения к объекту. Является идентификатором
Значение True этого свойства обеспечивает доступность кнопки для мыши или клавиатуры
Значение True этого свойства обеспечивает видимость кнопки во время выполнения приложения
Пример 3.6. Внешний вид формы в режиме конструктора дизайна:

Внешний вид формы при выполнении:

Кроме кнопок Button в Delphi применяются кнопки
и
, расположенные на палитре компонентов Additional.
Кнопки BitBtn — кнопки с изображением. Свойство Kind данного объекта позволяет выбрать кнопку с одним из стандартных изображений.
Кнопки SpeedBtn (кнопки с фиксацией и графикой) применяются тогда, когда требуется фиксация нажатого состояния.
Свойство Glyph позволяет вставить изображение из файла на кнопках BitBtn и SpeedBtn.
3.3. Элемент управления Label (метка)

Компонент Label (метка) предназначен для отображения текста на форме. На панели компонентов Standard метка изображена в виде , имя объекта — Label. Метка, помещенная на форму, получает имя LabelN, где N — номер 1, 2, 3… (пример 3.7).
Некоторые свойства компонента Label (метки), отличные от свойств компонента Button (кнопки), перечислены в таблице (пример 3.8).
Основным событием для компонента Label является OnClick.
Пример 3.9. Создать проект, в котором будет реализовано следующее действие: при щелчке мыши по кнопке «Приветствие» появляется «Здравствуй мир».
Этапы выполнения задания
- Изменить свойство Caption формы на «Работаем с кнопкой и меткой».
- Добавить на форму кнопку Button1.
- Изменить свойство Caption кнопки на «Приветствие».
- Добавить на форму метку Label1.
- Изменить свойства шрифта для компонента Label1. Нажать кнопку в поле Font (цвет шрифта — синий, размер — 20, стиль — жирный курсив).
- Очистить поле Caption у метки.
- В обработчик события OnClick для кнопки Button1 вписать команду
Label1.Caption := ‘Здравствуй, мир’ ;
Пример 3.7. Компонент Label на форме:

Пример 3.8. Свойства компонента Label:
Свойство
Назначение
Отображает введенный текст на форме
Устанавливает цвет фона метки. Работает только, если у свойства Transparent установлено значение false
Горизонтальное выравнивание текста относительно границ метки: taCenter (по центру), taLeftJustify (по левому краю), taRightJustify(по правому краю)
Значение true этого свойства приводит к автоматическому изменению размеров метки в соответствии с длиной текста
Вертикальное выравнивание текста относительно границ метки: tlCenter (по центру), tlBottom (по верхнему краю), tlTop (по нижнему краю)
Значение true (установлено по умолчанию) задает прозрачный фон метки
Значение true этого свойства обеспечивает автоматический перенос слов по строкам
Пример 3.9. Форма на этапе конструирования:


3.4. Элемент управления Edit (текстовое поле)

Edit (текстовое поле) — компонент, который предназначен для ввода и вывода текстовой информации. На панели компонентов Standard текстовое поле изображено в виде , имя объекта — Edit.
Компонент Edit, помещенный на форму, получает имя EditN, где N — номер 1, 2, 3… (пример 3.10).
В отличие от других рассмотренных компонентов, компонент Edit не обладает свойством Caption. Некоторые свойства компонента Edit приведены в таблице (пример 3.11).
Значение свойства Text можно задать на этапе конструирования, изменив его в инспекторе объектов. При выполнении программы пользователь, который вводит текст в компонент Edit, меняет значение свойства Text. Также свойство Text компонента Edit может изменяться программно. Основным событием компонента Edit является OnChange, которое происходит при изменении компонента. Наиболее часто программируют событие OnKeyPress, которое позволяет определить, какая клавиша была нажата.
Пример 3.12. Создать проект, в котором пользователя попросят ввести его имя (например, Елизавета), а затем, после нажатия клавиши Enter, будет выдано сообщение «Елизавета, приятно с Вами познакомиться!».
Этапы выполнения задания
- Изменить свойство Caption у формы на «Знакомство».
- Разместить на форме две метки и текстовое поле.
- Изменить свойство Caption у Label1 на «Введите свое имя и нажмите клавишу Enter».
- Очистить поле свойства Caption у Label2.
- Очистить поле свойства Text у Edit1.
- Написать обработчик события OnKeyPress для компонента Edit1, который будет проверять нажатие клавиши ввода (код клавиши Enter — 13). Если клавиша нажата, то поменять свойство Caption у Label2:
if key = #13 then
Label2.Caption := Edit1.Text +
‘, приятно с Вами познакомиться!’ ;
Текстовое поле Edit используется также для ввода и вывода чисел. При этом необходимо использовать функции для преобразования строк в числа и чисел в строки. Эти функции приведены в таблице (пример 3.13).
В PascalABC используются эти же функции для преобразования строковых данных в числовые и наоборот.
В русскоязычной версии Windows в качестве разделителя целой и дробной части числа по умолчанию используется запятая. Если при вводе чисел в текстовые поля использовать точку, то будет возникать ошибка преобразования типов.
Пример 3.14. Создать проект, в котором пользователь сможет ввести число, получить его значение в квадрате и квадратный корень из этого числа.
Этапы выполнения задания
- Изменить свойство Caption у формы на «Квадрат и корень».
- Разместить на форме три метки, три текстовых поля и кнопку.
- У компонентов Edit1, Edit2, Edit3 очистить поле свойства Text.
- Изменить свойство Caption у Label1 на «Введите неотрицательное число». Для размещения текста в две строки необходимо установить значение True у свойства WordWrap.
- Изменить свойство Caption у Label2 на «Квадрат числа».
- Изменить свойство Caption у Label3 на «Корень из числа».
- Изменить свойство Caption у Button1 на «Расчет».
- Написать обработчик OnClick для кнопки.
Пример 3.10. Компонент Edit (текстовое поле) на форме:

Пример 3.11. Свойства компонента Edit:
Свойство
Назначение
Определяет границу вокруг текстового поля: bsNone (нет границы), bsSingle (есть граница). Внешний вид границы можно изменять с помощью свойств BevelInner, BevelKind, BevelOuter
Ограничивает количество символов, которые можно ввести в Edit
Значение True запрещает редактирование текста, отображаемого в Edit
Содержит вводимый или выводимый текст
Текстовое поле часто называют однострочным редактором, поскольку оно снабжено такими функциями, как:
- копирование выделенного текста в буфер обмена (комбинация клавиш Ctrl+С);
- вырезание выделенного текста в буфер обмена (комбинация клавиш Ctrl+Х);
- вставка текста из буфера обмена в позицию курсора (комбинация клавиш Ctrl+V);
- отмена последней команды редактирования (комбинация клавиш Ctrl+Z).
Пример 3.12. Форма на этапе конструирования:

Работающее прило жение:

Пример 3.13. Функции преобразования чисел и строк:
Название функции
Действие
Ввод с помощью Edit
Преобразование строки в целое число
Преобразование строки в значение с плавающей запятой (соответствует типу экспоненциальный в Excel)
Вывод с помощью Edit
Преобразование целого числа в строку
Преобразование вещественного числа в строку
Преобразование вещественного числа в строку по заданному формату. Например, FloatToStrf(d, ffFixed,5,2) позволит вывести число занимающее 5 позиций, из которых 2 отводятся для дробной части числа
Пример 3.14. Форма на этапе конструирования:

Обработчик события OnClick для Button1.
procedure TForm1.Button1Click(Sender: TObject);
var a, b: integer;
Edit3.Text := FloatToStrF(c,
FFfixed, 7 , 3 );


Вместо двух компонентов Label и Edit можно использовать один LabeledEdit, сочетающий в себе свойства обоих компонентов. Находится компонент на палитре Additional: .
3.5. *Элементы управления CheckBox (флажок) и RadioButton (переключатель)

Компонент CheckBox (флажок) используется в приложениях для включения или выключения каких-либо опций. На панели компонентов Standard флажок изображен в виде , имя объекта — CheckBox. Флажок, помещенный на форму, получает имя CheckBoxN, где N — номер 1, 2, 3… (пример 3.15) . Некоторые свойства компонента CheckBox приведены в таблице (пример 3.16).

Компонент RadioButton (переключатель, радиокнопка) используется в приложениях для включения или выключения каких-либо опций. На панели компонентов Standard радиокнопка изображена в виде , имя объекта — RadioButton. Переключатель, помещенный на форму, получает имя — RadioButtonN, где N — номер 1, 2, 3… (см. пример 3.15) .
Свойства Caption, Alignment и Checked у радиокнопки совпадают с аналогичными свойствами флажка.
Обычно радиокнопки образуют группы взаимосвязанных переключателей, позволяющих выбрать только один из нескольких возможных вариантов. При размещении на форме нескольких переключателей включенным должен быть только один из них (компонент RadioGroup).
Пример 3. 17. Создать проект для вычисления частного от деления одного целого числа на другое. Числа задаются в текстовых полях. Результат вычисляется при нажатии на кнопку «Разделить» и помещается в третье текстовое поле. В зависимости от состояния флажка в результате выдается целое или вещественное значение частного.
Этапы выполнения задания
- Поместить на форму три текстовых поля, три надписи, флажок и кнопку.
- Очистить поля Text у всех компонентов Edit.
- Для компонента Edit3, в котором будет выводиться ответ, установить значение True для свойства ReadOnly.
- Изменить свойство Caption у компонентов Label («Делимое», «Делитель», «Частное»).
- Изменить свойство Caption компонента Button1 на «Разделить».
- Изменить свойство Caption компонента CheckBox1 на «Целочисленное деление».
- Написать обработчик события OnClick для компонента Button1.
7.1. Проверить, что поля компонентов Edit1 и Edit2 не пусты. Если это не так, то вывести сообщение «Одно из полей не заполнено».
7.2. Проверить состояние переключателя CheckBox. Если он включен, то выполнить целочисленное деление, иначе обычное деление.
7.3. Вывести результат. - Выполнить программу для различных значений. Проверить работу приложения, когда одно из полей Edit1 или Edit2 (или оба поля) пустые.
Пример 3.15. Компоненты CheckBox (флажок) и RadioButton (радиокнопка) на форме:

Пример 3.16. Свойства компонента CheckBox (флажок):
Свойство
Назначение
Значение True у этого свойства показывает, что компонент выделен (установлена галочка —
), при значении False компонент не выделен (пустое окно индикатора —
)
Значение False у этого свойства (установлено по умолчанию) допускает два состояния флажка: выделен и не выделен, значение True допускает три состояния флажка: выделен, не выделен и промежуточное

Позволяет выбрать одно из трех состояний флажка: cbChecked (выделен), cbGrayed(промежуточное значение — ) и cbUnchecked (не выделен) при значении True у свойства AllowGrayed
Надпись возле компонента CheckBox
Определяет с какой стороны кнопки размещается надпись: taLeftJustify (слева), taRightJustify (справа)
Пример 3.17. Форма на этапе конструирования:

Обработчик события OnClick для Button1.
procedure TForm1.Button1Click(Sender: TObject);
var a, b, c : integer;
d : real;
begin
if (Edit1.Text <> » ) and
(Edit2.Text <> » ) then
begin
a := StrToInt(Edit1.Text);
b := StrToInt(Edit2.Text);
if CheckBox1.checked then
begin
c := a div b;
Edit3.Text := IntToStr(c);
end
else
begin
d := a / b;
Edit3.Text := FloatToStrF(d, ffFixed, 5 , 2 );
end ;
end
else
ShowMessage( ‘Одно из полей
не заполнено’ );
end ;


Вещественный результат деления

Поля не заполнены
Вопросы к параграфу
1. Какие компоненты относят к элементам управления?
2. Как поместить компонент на форму?
3. Какие свойства компонента Button вы можете назвать?
4. Какое событие является основным для компонента Button?
5. Для чего предназначен компонент Label?
6. В каких случаях используется компонент Edit?
7. Для чего предназначены компоненты CheckBox и RadioButton?
Упражнения


1. Откройте проект из примера 3.9 и дополните его кнопкой «Очистить» [1] . Кнопка «Очистить» должна удалять текст метки (Свойству Caption присвоить значение пустой строки: «»). Сделайте случайным выбор цвета и размера шрифта у метки.
2. Откройте проект из примера 3.12 и добавьте на форму три метки и две кнопки.
Компонент
Свойство
Значение свойства
Пользовательские события
Каждый программист при разработке программ использует события для отслеживания действий пользователя или изменения значений, набор текста в текстовом поле и т.д. Но как насчет того, чтобы создать свои события в собственноручно созданом контроле. В этой статье мы и рассмотрим создание событий для вашего контрола.
Событие – это сообщение другим объектам программы, что произошло какое-то действие. Действие может быть вызвано пользователем, например нажатие мыши, или же другими элеметами программы. Объект, который вызывает событие называется отправитель сообщения, а объект, который сообщение получает – получатель. Получатель сообщения имеет метод, который автоматически выполняется в ответ на событие.
Платформа .NET Framework поддерживает простое программирование событий. Это настолько просто, что очень часто программисты не знают закулисную работу событий. Всё что нужно знать: если вы хотите получить событие от контрола, вы должны подписать обработчик события:
eventSource.someEvent += new SomeEventHandler(someEventMethod);
К примеру, если вы хотите подписаться к нажатию на кнопку button1 и чтобы это событие обрабатывал метод button1_Click, необходимо написать следующее:
button1.Click += new eventHandler(button1_Click);
После этого вы должны определить метод-обработчик следующим образом:
private void button1_Click(object sender, EventArgs e) < //код обработчика события >
Метод не обязательно должен быть скрытым (private), но он должен принимать два аргумента:
объекты типа Object и EventArgs. Теперь давайте рассмотрим создание наших собственных событий.
Предположим мы хотим создать событие MyEvent для элемента MyControl унаследованого от UserControl:
1. Первое что необходимо сделать – определить открытый делегат, который будет принимать два параметра: sender типа object и e типа MyEventArgs:
public delegate void MyEventHandler(object sender, MyEventArgs e); public partial class MyControl : UserControl
2. MyEventArgs – это объет содержащий данные, которые будут пересылаться от отправителя к получателю. MyEventArgs должен быть унаследован от System.EventArgs класса. Определим в нашем простанстве имен новый класс:
namespace MyControl < public class MyEventArgs : EventArgs < . >>
3. Определим событие MyEvent в классе нашего контрола:
public partial class MyControl : UserControl < //наше событие public event MyEventHandler MyEvent; public MyControl() < InitializeComponent(); >>
4. Теперь, в классе нашего контрола (MyControl) необходимо определить метод с именем которое соостоит из приставки On и названия нашего события. Поскольку наше событие мы назвали MyEvent, то метод будет называться OnMyEvent. Обратите внимание, что метод имеет один аргумент типа MyEventArgs. Внутри этого метода мы будем вызывать событие. В C# вызов события достигается путем вызова имени события:
protected virtual void OnMyEvent(MyEventArgs e)
5. Теперь, все что осталось сделать, это вызвать OnMyEvent из любого места. Откуда именно это сделать, зависит от того, что именно должно вызвать событие.
Теперь перейдем к практике. Мы создадим элемент управления, который будет похож на доску (10 х 10) в которой пользователь может вводить текст. Кроме того, существует курсор, который показывает текущую позицию редактирования. Пользователь может использовать комбинации клавиш, как например Ctrl+R, Ctrl+G, Ctrl+B чтобы изменять фоновый цвет элемента и Ctrl+Alt+R, Ctrl+Alt+G, Ctrl+Alt+B чтобы изменять цвет текста. Мы усовершенствуем наш элемент двумя событиями:
- ClineChanged – событие будет возникать, когда будет изменяться вертикальная позиция курсора
- ColumnChanged – при изменении гризонтальной позиции
После этого мы будем перехватывать эти события для динамического обновления метки, которая показывает текущее положение курсора. Дальше идет краткое описание нашего эелемента:
- Элемент содержит двумерный массив, который в свою очередь содержит символы вводимые пользователем. В конструкторе класса все элементы массива устанавливаются в пробелы.
- В методе OnPaint будут рисоваться символы в элементе строка за строкой, символ за символом.
- Курсор рисуется в отдельном потоке caretThread. Данный поток запускается в конструкторе класса и завязан на метод ShowsCaret. Этот метод содержит замкнутый цыкл, который показывает и прячет курсор каждые 350 милисекунд
- Поток caretThread завершается, когда удаляется элемент управления. Нами будет усовершенствован метод Dispose
- KeyPressed и ProcessDialogKey
- Определим всего два свойства CaretX и CaretY которые могут быть использованы для получения и изменения позиции курсора
отслеживают нажатия клавиш
Начнем с добавления событий нашему элементу управления: LineChanged и ColumnChanged. Определим два делегата для наших событий:
public delegate void LineEventHandler(object sender, LineEventArgs e); public delegate void ColumnEventHandler(object sender, ColumnEventArgs e);
Определим и реализуем LineEventArgs и ColumnEventArgs:
public class LineEventArgs : EventArgs < private int oldValue, newValue; public LineEventArgs(int oldValue, int newValue) < this.oldValue = oldValue; this.newValue = newValue; >public int NewLine < get < return newValue; >> public int OldLine < get < return oldValue; >> > public class ColumnEventArgs : EventArgs < private int oldValue, newValue; public ColumnEventArgs(int oldValue, int newValue) < this.oldValue = oldValue; this.newValue = newValue; >public int NewColumn < get < return newValue; >> public int OldColumn < get < return oldValue; >> >
У обеих классов конструкторы принимают два целочисленных значения: старое и новое. Оба класса имеют свойства доступные только для чтения. У класса LineEventArgs события OldLine и NewLine, а у класса ColumnEventArgs – OldColumn и NewColumn.
Теперь определим наши события LineChanged и ColumnChanged:
public event LineEventHandler LineChanged; public event ColumnEventHandler ColumnChanged;
Следующим шагом будет создание двух вирутальных методов с модификатором доступа protected: OnLineChanged и OnColumnChanged. В OnLineChanged мы вызываем событие LineChanged и в OnColumnChanged – ColumnChanged:
protected virtual void OnLineChanged(LineEventArgs e) < if(LineChanged != null) LineChanged(this, e); >protected virtual void OnColumnChanged(ColumnEventArgs e)
Теперь неоходимо вызвать методы OnLineChanged и OnColumnChanged из класса нашего элемента управления. Событие LineChanged срабатывает, когда изменяется вертиальная координата курсора, т.е. при изменении значеня свойства CaretY. Похоже происходит и с событием ColumnChanged. Оно происходит при изменении начения свойства CaretX. Определим эти свойтсва:
private int caretX, caretY; public int CaretX < get < return caretX; >set < int oldValue = caretX; caretX = value; if (oldValue != caretX) OnColumnChanged(new ColumnEventArgs(oldValue, caretX)); >> public int CaretY < get < return caretY; >set < int oldValue = caretY; caretY = value; if (oldValue != caretY) OnLineChanged(new LineEventArgs(oldValue, caretY)); >>
С событиями разобрались теперь перейдем к внешнему виду нашего элемента управления.
Для начала определим поля:
//количество строк int rowCount = 10; //количество столбцов int columnCount = 9; //массив, для хранения символов char[,] board; //размеры символа int charachterWidth = 10; int charachterHeight = 14; //расстояние между строками int lineSpace; //цвет текста public Color foreColor = Color.Black; Thread caretThread; //видимость курсора bool caretVisible = true; //толщина пера int penWidth = 2; Pen pen; bool keyStrokePressed;
В контрукторе класса заполним массив пробелами, подишемся на событие нажатия клавиш и создадим поток, который будет отображать курсор:
public MyControl() < InitializeComponent(); board = new char[columnCount, rowCount]; //заполняем массив пробелами for (int i = 0; i < columnCount; i++) < for (int j = 0; j < rowCount; j++) board[i, j] = ' '; >pen = new Pen(foreColor, penWidth); this.BackColor = Color.White; //подписываемся на события нажатия клавиш this.KeyPress += new KeyPressEventHandler(KeyPressed); //поток, отображающий курсор caretThread = new Thread(new ThreadStart(ShowCaret)); caretThread.Start(); >
Метод, который будет отображать и скрывать курсор:
void ShowCaret() < try < while (true) < this.Invalidate(new Rectangle(CaretX * charachterWidth, CaretY * (charachterHeight + lineSpace), CaretX * charachterWidth + 2 * penWidth, (CaretY + 1) * (charachterHeight + lineSpace))); Thread.Sleep(350); caretVisible = !caretVisible; >> catch (Exception ex) < >>
Переопределим метод OnPaint который будет отрисовывать наш элемент:
protected override void OnPaint(PaintEventArgs e) < Graphics g = e.Graphics; Font font = new Font("Verdana", charachterWidth); Brush brush = new SolidBrush(foreColor); //рисуем символы for (int i = 0; i < columnCount; i++) for (int j = 0; j < rowCount; j++) < g.DrawString(board[i, j].ToString(), font, brush, new Point(i * charachterWidth, j * (lineSpace + charachterHeight))); >//рисуем курсор if (caretVisible) < int x = CaretX * charachterWidth; int y = CaretY * (charachterHeight + lineSpace); g.DrawLine(pen, x, y, x, y + lineSpace + charachterHeight); >>
Теперь займемся обработкой нажатия клавиш. Здесь будут использоваться два ообработчика события: ProcessDialogKey и KeyPressed:
void KeyPressed(object sender, KeyPressEventArgs e) < if (!keyStrokePressed) < char c = e.KeyChar; int i = (int)c; if (i == 8) < if (CaretX == 0) < CaretX = columnCount - 1; if (CaretY == 0) CaretY = rowCount - 1; else CaretY--; >else < CaretX--; >board[CaretX, CaretY] = ' '; > else < board[CaretX, CaretY] = c; if (CaretX == columnCount - 1) < CaretX = 0; if (CaretY == rowCount - 1) CaretY = 0; else CaretY++; >else CaretX++; > this.Invalidate(); this.Update(); > > protected override bool ProcessDialogKey(Keys keyData) < keyStrokePressed = true; switch (keyData) < case Keys.Down: if (CaretY == rowCount - 1) CaretY = 0; else CaretY++; break; case Keys.Up: if (CaretY == 0) CaretY = rowCount - 1; else CaretY--; break; case Keys.Left: if (CaretX == 0) < CaretX = columnCount - 1; if (CaretY == 0) CaretY = rowCount - 1; else CaretY--; >else CaretX--; break; case Keys.Right: if (CaretX == columnCount - 1) < CaretX = 0; if (CaretY == rowCount - 1) CaretY = 0; else CaretY++; >else CaretX++; break; case Keys.Control | Keys.R: this.BackColor = Color.Red; break; case Keys.Control | Keys.G: this.BackColor = Color.Green; break; case Keys.Control | Keys.B: this.BackColor = Color.Blue; break; case Keys.Control | Keys.Alt| Keys.R: foreColor = Color.Red; break; case Keys.Control | Keys.Alt | Keys.G: foreColor = Color.Green; break; case Keys.Control | Keys.Alt | Keys.B: foreColor = Color.Blue; break; case Keys.Escape: this.BackColor = Color.White; break; case Keys.Alt|Keys.F4: Application.Exit(); break; default : if ((int)(Keys.Control & keyData) != 0) < //нажата клавиша Control, если есть //необходимость, выполняйте какие-то действия return true; >else if ((int)(Keys.Alt & keyData) != 0) < //нажата клавиша Alt, если есть //необходимость, выполняйте какие-то действия return true; >else < // даем возможность выполниться коду в KeyPressed keyStrokePressed = false; >break; > this.Invalidate(); this.Update(); return base.ProcessDialogKey(keyData); >
Осталось изменить метод Dispose – удаление объекта. Для этого, открываем файл MyControl.Designer.cs и в нем изменяем метод Dispose
protected override void Dispose(bool disposing) < if (disposing && (components != null)) < components.Dispose(); >if (disposing) caretThread.Abort(); base.Dispose(disposing); >
Теперь, после сборки проекта, мы можем использовать наш элемент управления. Для этого, создадим Windows Forms Application в нашем решении (рис. 1). Я назвал приложение MyControlTest:

Рис.1 Добавление проекта для теста
Для того, чтобы добавить наш элемент управления: Tools -> Choose Toolbbox Item. В появившемся окне на влкадке .NET Framework Components жмем Browse (Рис. 2).

Рис. 2 Добавить элемент управления
Далее выбираем наш контрол. В моем случае, он находится в папке с проектом MyControl в подпаке Debug (у Вас может находится в папке Release). После добавления на панели компонентов должен появиться наш элемент управления (Рис. 3) (о том, как изменить стандартную иконку на свою, читайте здесь).

Рис. 3 Пользовательский элемент управления
Добавляем его на форму и ползьуемся. Для наглядности, я добавил два лейбла, которые показывают текущее положение курсора (Рис. 4)

Рис. 4 Использование пользовательского элемента
[download /> Переведено с сайта www.ondotnet.com
- February 2014 (1)
- January 2014 (1)
- March 2013 (2)
- February 2013 (2)
- November 2012 (1)
- October 2012 (2)
- July 2012 (3)
- May 2012 (2)
- January 2012 (4)
- December 2011 (3)
- November 2011 (14)
- October 2011 (1)
ASP.NET – обработка событий
Событие – это действие или событие, такое как щелчок мыши, нажатие клавиши, движения мыши или любое системное уведомление. Процесс общается через события. Например, прерывания являются сгенерированными системой событиями. Когда происходят события, приложение должно иметь возможность реагировать на него и управлять им.
События в ASP.NET вызываются на клиентском компьютере и обрабатываются на сервере. Например, пользователь нажимает кнопку, отображаемую в браузере. Событие Click происходит. Браузер обрабатывает это событие на стороне клиента, отправляя его на сервер.
На сервере есть подпрограмма, описывающая, что делать при возникновении события; это называется обработчиком событий. Поэтому, когда сообщение о событии передается на сервер, он проверяет, имеет ли событие Click связанный обработчик события. Если это так, обработчик события выполняется.
Аргументы событий
Обработчики событий ASP.NET обычно принимают два параметра и возвращают void. Первый параметр представляет объект, вызывающий событие, а второй параметр – аргумент события.
Общий синтаксис события:
private void EventName (object sender, EventArgs e);
События приложений и сессий
Наиболее важные события приложения:
- Application_Start – возникает при запуске приложения / веб-сайта.
- Application_End – возникает при остановке приложения / веб-сайта.
Application_Start – возникает при запуске приложения / веб-сайта.
Application_End – возникает при остановке приложения / веб-сайта.
Точно так же наиболее часто используемые события сеанса:
- Session_Start – возникает, когда пользователь впервые запрашивает страницу из приложения.
- Session_End – Возникает, когда сессия заканчивается.
Session_Start – возникает, когда пользователь впервые запрашивает страницу из приложения.
Session_End – Возникает, когда сессия заканчивается.
События страницы и управления
Общие страницы и управляющие события:
- DataBinding – вызывается, когда элемент управления связывается с источником данных.
- Уничтожено – поднимается, когда страница или элемент управления освобождаются.
- Ошибка – это событие страницы, возникающее при возникновении необработанного исключения.
- Init – вызывается при инициализации страницы или элемента управления.
- Load – поднимается, когда страница или элемент управления загружены.
- PreRender – вызывается, когда должна отображаться страница или элемент управления.
- Выгрузить – поднимается, когда страница или элемент управления выгружаются из памяти.
DataBinding – вызывается, когда элемент управления связывается с источником данных.
Уничтожено – поднимается, когда страница или элемент управления освобождаются.
Ошибка – это событие страницы, возникающее при возникновении необработанного исключения.
Init – вызывается при инициализации страницы или элемента управления.
Load – поднимается, когда страница или элемент управления загружены.
PreRender – вызывается, когда должна отображаться страница или элемент управления.
Выгрузить – поднимается, когда страница или элемент управления выгружаются из памяти.
Обработка событий с использованием элементов управления
Все элементы управления ASP.NET реализованы в виде классов, и у них есть события, которые запускаются, когда пользователь выполняет над ними определенные действия. Например, когда пользователь нажимает кнопку, генерируется событие «Клик». Для обработки событий есть встроенные атрибуты и обработчики событий. Обработчик события закодирован, чтобы отвечать на событие и предпринимать соответствующие действия для него.
По умолчанию Visual Studio создает обработчик событий, добавляя предложение Handles в процедуру Sub. В этом разделе указывается элемент управления и событие, которое обрабатывает процедура.
Тег ASP для кнопки управления:
ID="btnCancel" runat="server" Text="Cancel" />
Обработчик события для события Click:
Protected Sub btnCancel_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnCancel.Click End Sub
Событие также может быть закодировано без предложения Handles. Затем обработчик должен быть назван в соответствии с соответствующим атрибутом события элемента управления.
Тег ASP для кнопки управления:
ID="btnCancel" runat="server" Text="Cancel" Onclick="btnCancel_Click" />
Обработчик события для события Click:
Protected Sub btnCancel_Click(ByVal sender As Object, ByVal e As System.EventArgs) End Sub
Общие контрольные события:
| Событие | атрибут | управления |
|---|---|---|
| Нажмите | По щелчку | Кнопка, кнопка изображения, кнопка ссылки, карта изображения |
| команда | По команде | Кнопка, кнопка изображения, кнопка ссылки |
| TextChanged | OnTextChanged | Текстовое окно |
| SelectedIndexChanged | OnSelectedIndexChanged | Выпадающий список, список, список переключателей, список флажков. |
| CheckedChanged | OnCheckedChanged | Флажок, переключатель |
Некоторые события вызывают немедленную отправку формы на сервер, они называются событиями обратной передачи. Например, событие щелчка, например, Button.Click.
Некоторые события не публикуются на сервере немедленно, они называются событиями без обратной передачи.
Например, события изменения или события выбора, такие как TextBox.TextChanged или CheckBox.CheckedChanged. События nonpostback могут быть отправлены обратно немедленно, если для их свойства AutoPostBack установлено значение true.
События по умолчанию
Событием по умолчанию для объекта Page является событие загрузки. Точно так же каждый элемент управления имеет событие по умолчанию. Например, событием по умолчанию для элемента управления кнопки является событие Click.
Обработчик событий по умолчанию можно создать в Visual Studio, просто дважды щелкнув элемент управления в режиме конструктора. В следующей таблице приведены некоторые события по умолчанию для общих элементов управления:
| контроль | Событие по умолчанию |
|---|---|
| AdRotator | AdCreated |
| Маркированный список | Нажмите |
| кнопка | Нажмите |
| каландр | SelectionChanged |
| CheckBox | CheckedChanged |
| CheckBoxList | SelectedIndexChanged |
| DataGrid | SelectedIndexChanged |
| DataList | SelectedIndexChanged |
| Выпадающий список | SelectedIndexChanged |
| Гиперссылка | Нажмите |
| ImageButton | Нажмите |
| ImageMap | Нажмите |
| LinkButton | Нажмите |
| ListBox | SelectedIndexChanged |
| Меню | MenuItemClick |
| Переключатель | CheckedChanged |
| RadioButtonList | SelectedIndexChanged |
пример
Этот пример включает в себя простую страницу с элементом управления надписью и кнопкой. Когда происходят события страницы, такие как Page_Load, Page_Init, Page_PreRender и т. Д., Он отправляет сообщение, которое отображается элементом управления меткой. Когда кнопка нажата, возникает событие Button_Click, которое также отправляет сообщение для отображения на ярлыке.
Создайте новый веб-сайт и перетащите элемент управления меткой и элемент управления на него из панели инструментов элемента управления. Используя окно свойств, установите идентификаторы элементов управления как .lblmessage. и .btnclick. соответственно. Установите свойство Text элемента управления Button как «Клик».
Файл разметки (.aspx):
Page Language="C#" AutoEventWireup="true" CodeBehind="Default.aspx.cs" Inherits="eventdemo._Default" %> xmlns="http://www.w3.org/1999/xhtml" > runat="server"> Untitled Page id="form1" runat="server"> ID="lblmessage" runat="server" > /> /> /> ID="btnclick" runat="server" Text="Click" onclick="btnclick_Click" />
Дважды щелкните в представлении конструктора, чтобы перейти к коду позади файла. Событие Page_Load создается автоматически без какого-либо кода. Запишите следующие понятные строки кода:
using System; using System.Collections; using System.Configuration; using System.Data; using System.Linq; using System.Web; using System.Web.Security; using System.Web.UI; using System.Web.UI.HtmlControls; using System.Web.UI.WebControls; using System.Web.UI.WebControls.WebParts; using System.Xml.Linq; namespace eventdemo public partial class _Default : System.Web.UI.Page protected void Page_Load(object sender, EventArgs e) lblmessage.Text += "Page load event handled.
"; if (Page.IsPostBack) lblmessage.Text += "Page post back event handled.
"; > > protected void Page_Init(object sender, EventArgs e) lblmessage.Text += "Page initialization event handled.
"; > protected void Page_PreRender(object sender, EventArgs e) lblmessage.Text += "Page prerender event handled.
"; > protected void btnclick_Click(object sender, EventArgs e) lblmessage.Text += "Button click event handled.
"; > > >
Выполнить страницу. Метка показывает загрузку страницы, инициализацию страницы и события предварительной визуализации страницы. Нажмите кнопку, чтобы увидеть эффект: