ПОНЯТНО О Visual Basic NET (том 2)

Делаем будильник


Поместим в рамку с именем Будильник все объекты, необходимые для будильника:

  • Метку с именем Метка_будильника
  • Текстовое поле с именем Циферблат_будильника
  • Кнопку с именем Кнопка_включения_выключения_будильника
  • Кнопку с именем Кнопка_выключения_звонка
  • В циферблат занесем в режиме проектирования текст 12:00:00.  Просто для того, «чтобы было». В качестве циферблата мы выбрали текстовое поле, а не метку. А это для того, чтобы иметь возможность в режиме работы вручную устанавливать время будильника.

    Заставляем будильник звучать. Давайте пока забудем обо всех этих кнопках, метках и прочих подробностях, а возьмем быка за рога и заставим будильник при совпадении времени на часах и на будильнике исполнять какую-нибудь мелодию.

    Вспомните, как мы занимались музыкой в «Плеере». Поместите на форму Windows Media Player и дайте ему имя Звонок. Сделайте его невидимым. Для настройки звонка достаточно трех операторов в процедуре Form1_Load:

            Звонок.AutoStart = False         'Чтобы не запускался слишком рано

            Звонок.PlayCount = 0               'Чтобы  закончив играть, начинал снова

            Звонок.FileName = "Mozart's Symphony No. 40.RMI"

    Эта троица, несмотря на то, что встретится в программе скорее всего только один раз, в глазах программиста просится стать процедурой. Здесь принцип такой:

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

    Это улучшит понятность и читабельность программы – один из важнейших факторов ее качества.



    Запустит воспроизведение мелодии оператор Звонок.Play(), но он должен выполниться только тогда, когда время на циферблате часов совпадет со временем на циферблате будильника.

    Вот как дополнится теперь наш проект (я показываю только те процедуры, которых коснулись дополнения):

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

            Настройка_звонка()


            Смена_даты_и_дня_недели()
    End Sub
    Private Sub Таймер_часов_Tick( ByVal sender As Object, ByVal e As EventArgs)  Handles Таймер_часов.Tick
            Время_на_часах = Format(Now, "HH:mm:ss")
            Циферблат_часов.Text = Время_на_часах
            If Время_на_часах = "00:00:00" Then Смена_даты_и_дня_недели()
            If Время_на_часах = Циферблат_будильника.Text Then Звонок.Play()
    End Sub
    Sub Настройка_звонка()
            Звонок.AutoStart = False         'Чтобы не запускался слишком рано
            Звонок.PlayCount = 0              'Чтобы  закончив играть, начинал снова
            Звонок.FileName = "Mozart's Symphony No. 40.RMI"
    End Sub
    Запустите проект и установите время на циферблате будильника. Дождитесь, когда будильник зазвонит. Завершите работу проекта, не дожидаясь конца мелодии.
    Два состояния будильника. Пора заняться кнопками и меткой. Подумаем вот о чем. Во время работы будильник в каждый момент времени может находиться в одном из двух состояний: «Установлен» или «Не установлен». Состояние «Установлен» означает, что вы хотите, чтобы будильник, когда подойдет его срок, звонил. Состояние «Не установлен» означает, что вы не хотите, чтобы будильник звонил, даже когда подойдет его срок. Компьютер должен в любой момент времени знать, в каком именно состоянии находится будильник, чтобы принять решение – звонить или не звонить. В таких случаях, когда компьютер должен в любой момент что-то знать или помнить, программист всегда придумывает переменную величину, дает ей подходящее имя и тип и организует хранение в этой переменной той самой информации, которую нужно помнить.
    Придумаем переменную и дадим ей имя Будильник_установлен. Каким типом ее объявить? Для этого надо понять, а какие значения будет принимать эта переменная? По смыслу задачи значений два – «да» и «нет». Можно придать ей тип String, но хорошая практика программирования диктует тип Boolean. Вы скоро привыкнете к нему и поймете, что он удобнее.
    Кнопки и метка будильника. Теперь попробуем вообразить, что должно происходить при включении будильника:


    • Нужно сообщить компьютеру, что будильник установлен

    • Нужно, чтобы текст над циферблатом был такой: «Будильник установлен на»

    • Нужно, чтобы текст на кнопке был такой: «Выключить будильник»

    • В соответствии с этим пишем процедуру:
      Sub Включить_будильник()
              Будильник_установлен = True
              Метка_будильника.Text = "Будильник установлен на"
              Кнопка_включения_выключения_будильника.Text = "Выключить будильник"
      End Sub
      Теперь попробуем сообразить, что должно происходить при выключении будильника:
      • Нужно сообщить компьютеру, что будильник не установлен

      • Нужно, чтобы текст над циферблатом был такой: «Будильник отключен»

      • Нужно, чтобы текст на кнопке был такой: «Включить будильник»

      • В соответствии с этим пишем процедуру:
        Sub Выключить_будильник()
                Будильник_установлен = False
                Метка_будильника.Text = "Будильник отключен"
                Кнопка_включения_выключения_будильника.Text = "Включить будильник"
        End Sub
        Теперь нам удивительно легко написать процедуру щелчка по кнопке включения-выключения будильника:
        Private Sub Кнопка_включения_выключения_будильника_Click(ByVal sender As System.Object,  _
        ByVal e As System.EventArgs) Handles Кнопка_включения_выключения_будильника.Click
                If Будильник_установлен Then Выключить_будильник() Else Включить_будильник()
        End Sub
        Обратите внимание, что благодаря удачному выбору имен и структуры программы язык программы по своей понятности приближается к естественному, человеческому.
        Напомню, что поскольку переменная  Будильник_установлен имеет логическое значение True или False, ее можно в одиночку использовать в качестве условия оператора If. Поэтому совсем не обязательно было писать
        If Будильник_установлен = True Then ….
        Процедуру щелчка по кнопке выключения звонка приведу без пояснений:
        Private Sub Кнопка_выключения_звонка_Click(ByVal sender As System.Object,  _
        ByVal e As System.EventArgs)  Handles Кнопка_выключения_звонка.Click
                Звонок.Stop()


        End Sub
        В последних четырех процедурах заключена вся механика работы кнопок и метки. Теперь надо позаботиться о том, чтобы будильник звенел только тогда, когда включен. Для этого вместо оператора
                If Время_на_часах = Циферблат_будильника.Text Then Звонок.Play()
        мы пишем оператор
                If Будильник_установлен And Время_на_часах = Циферблат_будильника.Text Then Звонок.Play()
        Теперь нужно решить, должен ли будильник после запуска проекта быть включен или выключен. Можно решить и так и эдак, на работоспособность проекта это никак не повлияет. Я предпочитаю, чтобы он был выключен, поэтому пишу в процедуру Form1_Load оператор Выключить_будильник().
        Программа часов с будильником целиком. Часы с будильником готовы. Приведу полностью их программу:
        Public Class Form1
            Inherits System.Windows.Forms.Form
        Windows Form Designer generated code
            Dim Время_на_часах As String
            Dim Будильник_установлен As Boolean
            Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs)Handles MyBase.Load
                Настройка_звонка()
                Выключить_будильник()
                Смена_даты_и_дня_недели()
            End Sub
            Private Sub Таймер_часов_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles Таймер_часов.Tick
                Время_на_часах = Format(Now, "HH:mm:ss")
                Циферблат_часов.Text = Время_на_часах
                If Время_на_часах = "00:00:00" Then Смена_даты_и_дня_недели()
                If Будильник_установлен And Время_на_часах = Циферблат_будильника.Text Then Звонок.Play()
            End Sub
            Sub Настройка_звонка()
                Звонок.AutoStart = False
                Звонок.PlayCount = 0
                Звонок.FileName = "Mozart's Symphony No. 40.RMI"
            End Sub
            Sub Смена_даты_и_дня_недели()
                Циферблат_даты.Text = Format(Now, "Long Date")
                Циферблат_дня_недели.Text = Format(Now, "dddd")
            End Sub
            Sub Включить_будильник()
                Будильник_установлен = True


                Метка_будильника.Text = "Будильник установлен на:"
                Кнопка_включения_выключения_будильника.Text = "Выключить будильник"
            End Sub
            Sub Выключить_будильник()
                Будильник_установлен = False
                Метка_будильника.Text = "Будильник отключен"
                Кнопка_включения_выключения_будильника.Text = "Включить будильник"
            End Sub
            Private Sub Кнопка_включения_выключения_будильника_Click(ByVal sender As System.Object,  _
        ByVal e As System.EventArgs) Handles Кнопка_включения_выключения_будильника.Click
                If Будильник_установлен Then Выключить_будильник() Else Включить_будильник()
            End Sub
            Private Sub Кнопка_выключения_звонка_Click(ByVal sender As System.Object,  _
        ByVal e As System.EventArgs)  Handles Кнопка_выключения_звонка.Click
                Звонок.Stop()
            End Sub
        End Class
        Еще раз о стиле. Вы, наверное, заметили, что если после запуска проекта вы заставляли будильник звенеть несколько раз, то каждый раз он начинал мелодию не с начала, а с того места, где вы звонок выключили. Мне это все равно, но если вам это не нравится, то вы должны включать звонок не одним оператором
                Звонок.Play()
        а парой операторов:
                Звонок. CurrentPosition = 0
                Звонок.Play()
        Но в этом случае вместо
                If Будильник_установлен And Время_на_часах = Циферблат_будильника.Text Then Звонок.Play()
        вам придется писать
                If Будильник_установлен And Время_на_часах = Циферблат_будильника.Text Then
                    Звонок.CurrentPosition = 0
                    Звонок.Play()
                End If
        Вы видите, что оператор включения звонка теряет прозрачность и краткость. Выход один: оформлять эту пару операторов, как процедуру Включить_звонок. Тогда можно будет написать
                If Будильник_установлен And Время_на_часах = Циферблат_будильника.Text Then Включить_звонок()
        Вот теперь оператор включения звонка приобрел элегантность и максимальную понятность. Теперь  никто не обвинит нас в корявости стиля. К тому же, если нам в будущем захочется как-то улучшить включение звонка, то все изменения мы сможем делать внутри процедуры Включить_звонок, не трогая сам оператор.

        Содержание раздела