Онлайн
библиотека книг
Книги онлайн » Разная литература » Интернет-журнал "Домашняя лаборатория", 2008 №7 - Журнал «Домашняя лаборатория»

Шрифт:

-
+

Закладка:

Сделать
1 ... 173 174 175 176 177 178 179 180 181 ... 192
Перейти на страницу:
запрограммировать секундомер, нам нужно познакомиться с новым типом переменных величин. Необходимость в нем в нашем проекте вытекает вот откуда. Если будильник в каждый момент времени может находиться в одном из двух состояний (установлен или не установлен), то секундомер — в трех: считает, стоит в паузе, стоит в нуле. Придумаем переменную и дадим ей имя Режим_работы_секундомера. Объявить ее типом Boolean явно недостаточно, ведь в типе Boolean всего два возможных значения, а нам нужно три. Можно придать ей тип String, но хорошая практика программирования диктует другое.

В Visual Basic нет типа данных, в котором переменная имела бы ровно три значения, зато Visual Basic, как и многие языки, позволяет программисту создавать собственные типы. Наша задача — создать тип, в котором переменная принимает ровно три значения: считает, пауза, в нуле — а затем объявить этим типом переменную Режим_работы_секундомера.

В нашем случае для создания такого типа достаточно записать выше процедур конструкцию:

Private Enum типРежим_работы_секундомера

считает

пауза

в_нуле

End Enum

Это не процедура, хоть и похожа. Слово Enum означает, что тип — перечислимый. Это означает, что мы обязаны были придумать и в этой конструкции перечислить имена всех возможных значений переменной этого типа, что мы и сделали. Поскольку каждый тип должен иметь свое имя (Integer, String…), нам тоже пришлось придумать имя новому типу (типРежим_работы_секундомера) и указать его в заголовке.

Теперь, когда новый тип определен, можно любую переменную объявить этим типом, что мы и делаем:

Dim Режим_работы_секундомера As типРежим_работы_секундомера

Замечание для новичков: Новички с трудом воспринимают смысл строк со стоящими рядом похожими именами, таких, например, как только что написанная. Новичку кажется, что эти имена означают одно и то же. Должен сказать, что профессиональные программисты специально обозначают близкие вещи похожими именами, им так больше нравится (можете себе вообразить?!). Например, у них может встретиться кнопка с именем сmdПодать_сюда_Ляпкина_Тяпкина и в этом же проекте переменная с именем strПодать_сюда_Ляпкина_Тяпкина. Для того, чтобы отличать одно от другого, они начинают каждое имя с префикса, который говорит программисту (не компьютеру!) о том, кому принадлежит имя (кнопке (префикс cmd), строковой переменной (префикс str) или кому-нибудь другому). Со временем вы поймете неизбежность такого подхода, а пока вам придется быть внимательным и не путать близкие имена.

Делаем секундомер

Поместим на форму элементы управления и дадим им имена:

Таймер_секундомера Циферблат_секундомера Кнопка_пуска_паузы_секундомера Кнопка_обнуления_секундомера а также не забудем метку и рамочку.

Будем использовать следующие переменные:

Dim Режим_работы_секундомера As типРежим_работы_секундомера

Dim Время_на_секундомере As Single

Dim Время_запуска_секундомера As Single

Dim Время_на_паузе_секундомера As Single

Dim Цифра_десятых As Long

Обратите внимание, что все переменные времени объявлены, как дробные числовые, а не как Date. Сейчас вам станет ясно, почему.

Давайте по порядку. Таймер нужен секундомеру для того же, для чего и часам, а именно — чтобы вовремя менялись цифры на циферблате, а собственный таймер нужен для того, чтобы не зависеть от часов. Поскольку нам нужно отслеживать десятые доли секунды, установим ему интервал поменьше, например 10 или 5 — не играет роли. Когда секундомер считает, таймер секундомера должен работать: Таймер_секундомера. Enabled = True

а когда он в паузе или в нуле, таймер должен стоять Таймер_секундомера. Enabled = False

Для отсчета времени на секундомере мы будем использовать известную вам функцию Timer (не путайте с элементом управления Timer), потому что она выдает с приемлемой для нас точностью десятые доли секунды (какой же секундомер без десятых). Поскольку она выдает число секунд, прошедших с полуночи, а нам нужно число секунд, прошедших с момента запуска секундомера, да еще с учетом того, что во время паузы на секундомере уже стояли какие-то показания, нам придется поразмыслить, как это сделать.

Засечем в момент пуска секундомера значение функции Timer оператором Время_запуска_секундомера = Timer

Тогда в каждый момент времени после запуска секундомера выражение (Timer — Время_запуска_секундомера) как раз и будет равняться числу секунд, прошедших с момента запуска секундомера. А если нам удастся правильно засечь Время_на_паузе_секундомера (выраженное в секундах, прошедших с момента пуска), то дело решит оператор

Время_на_секундомере = (Timer — Время_запуска_секундомера) + Время_на_паузе_секундомера

Если поместить его в процедуру таймера, то он будет оперативно выдавать нужное Время_на_секундомере. Задача решена.

Теперь займемся внешним видом показаний секундомера. Время_на_секундомере — это дробное число — количество секунд. Например, такое — 67,2. А нам хотелось бы получить его в таком виде — 00:01:07.2. Для этого нам нужно как-то преобразовать число секунд в стандартный формат времени. Дело решает оператор:

Циферблат_секундомера.Text = DateAdd ("s", Время_на_секундомере, #12:00:00 AM#)

Здесь время #12:00:00 AM# обозначает, как ни странно, полночь по-американски. Задача решена.

Но функция DateAdd оставляет за бортом десятые доли секунды. Попробуем выделить их из числа Время_на_секундомере. Для этого мысленно проведем такую цепочку операций с использованием функции Int:

Целая часть = Int (Время_на_секундомере)

Дробная часть = Время_на_секундомере — Целая часть Цифра_десятых = Int (10 * Дробная часть)

Сведем эти три оператора в один:

Цифра_десятых = Int(10 * (Время_на_секундомере

Int(Время_на_секундомере)))

и дополним оператор вывода времени на циферблат секундомера: Циферблат_секундомера.Text = DateAdd ("s", Время_на_секундомере, #12:00:00 AM#) & & Цифра_десятых

Здесь знак & является удобным заменителем знака + для сборки данных в одну строку. Я рекомендую пользоваться именно им, так как компьютер его уж никак не спутает со сложением чисел. Между целой и дробной частью секунд я решил поставить точку. Обратите внимание, что знак & без проблем соединяет данные трех разных типов: функцию DateAdd, строку и число Цифра_десятых.

Ну вот, пожалуй, и все объяснения. В остальном вы сможете разобраться сами, прочитав текст программы, так как ничего нового по сравнению с будильником не обнаружите.

После этого самые дотошные скажут мне, что нечего было огород городить — создавать новый тип данных, когда можно было обойтись логической переменной Секундомер_считает. Верно, но неправильно. Потому что нужно оставлять простор для дальнейшего развития проекта. Например, вы можете захотеть, чтобы во время паузы цифры на секундомере мигали, а в нуле — нет. Отличить одно состояние от другого вам и поможет переменная Режим_работы_секундомера.

Недостатки проекта

Мой проект работает на первый взгляд нормально, я проверял и часы, и будильник, и секундомер. Но делал я это не так тщательно, как положено при тестировании, поэтому в нем вполне возможны ошибки. Вот те, что я сумел заметить, но не стал исправлять, предоставив это вам:

В будильнике, если сигнал завершился сам, без нажатия кнопки "Выключить сигнал", то

1 ... 173 174 175 176 177 178 179 180 181 ... 192
Перейти на страницу: