В мир информатики # 88 (16—31 марта).
Школа программирования
Oсновы программирования
на Visual Basic
Н.М. Тимофеева,
г. Обнинск Калужской обл.
Продолжение. Начало см. “В мир
информатики” № 69–73, 78–80, 83, 85 (“Информатика” № 4–8, 19–21, 24/2006,
3–4/2007)
Пример программирования № 10 “Вечный
календарь”
Постановка задачи
Разработайте программу,
представляющую собой вечный календарь (она
должна показывать календарь для любого месяца с
1901 по 2099 год).
План решения
На рис. 1 показан предлагаемый
дизайн экрана:

Рис. 1
Назначение каждого элемента
управления:
1) вертикальная полоса прокрутки (VScrollBar)
— для выбора номера года (перемещение
“ползунка” полосы прокрутки будет менять
значение в надписи);
2) надпись — для показа года,
установленного с помощью полосы прокрутки;
3) список (ListBox) — для выбора названия
месяца из двенадцати названий;
4) блок картинки (PictureBox) — для показа
календаря конкретного месяца конкретного года
(см. рис. 3 ниже);
5) кнопки — для выполнения следующих
действий по щелчку на них:
— Показать — для показа календаря
в блоке картинки;
— Очистить — для очистки блока;
— Выход — для завершения
программы.
N–S-диаграммы для разработки процедур:
1) процедура для загрузки формы:

4) процедура для кнопки Показать:

4) процедура для кнопки Очистить:

В программе будет использоваться так
называемая “пользовательская”2 функция с
именем ЧислоДней для определения количества
дней в выбранном месяце (с учетом выбранного
года). Для нее N–S-диаграмма имеет вид:

Создание интерфейса
Разместите на форме три кнопки, одну
надпись, одну вертикальную полосу прокрутки,
один список (ListBox) и один блок картинки (PictureBox)
— см. рис. 2.

Рис. 2
Установка свойства
Установите следующие свойства формы и
элементов управления:


Написание кода
Код для формы:
Private Sub Form_Load()
'Заполняем список
With lstМесяц
.AddItem "Январь"
.AddItem "Февраль"
.AddItem "Март"
.AddItem "Апрель"
.AddItem "Май"
.AddItem "Июнь"
.AddItem "Июль"
.AddItem "Август"
.AddItem "Сентябрь"
.AddItem "Октябрь"
.AddItem "Ноябрь"
.AddItem "Декабрь"
'Устанавливаем по умолчанию Январь
.ListIndex = 0
'Нумерация элементов списка
'начинается с нуля
End With
End Sub
Код для вертикальной полосы прокрутки:
Private Sub vsbГод_Change()
'Присваиваем значение свойства Value
'полосы прокрутки
'значению свойства Caption надписи
lblГод.Caption = vsbГод.Value
End Sub
Функция, которая определяет
количество дней в месяце, имеет вид:
Private Function ЧислоДней (ByVal АргМесяц As String,
ByVal АргГод As Integer) As Integer
Select Case АргМесяц
Case "Январь", "Март",
"Май", "Июль", "Август",
"Октябрь", "Декабрь"
ЧислоДней = 31
Case "Апрель", "Июнь",
"Сентябрь", "Ноябрь"
ЧислоДней = 30
Case "Февраль"
ЧислоДней = 28
If АргГод Mod 4 = 0 Then
'Високосный год3
ЧислоДней = 29
End If
End Select
End Function
Код для кнопки Показать:
Private Sub cmdПоказать_Click()
Dim Месяц As String, Год As Integer,
ПервДень As String
Dim I As Integer, День As Integer
'Выбранный в списке месяц
Месяц = lstМесяц.Text
'Выбранный с помощью полосы прокрутки
год
Год = vsbГод.Value
'Очищаем блок картинки
picМесяц.Cls
'Печатаем в нем выбранные месяц и год
picМесяц.Print Tab(6); Месяц; ""; Год
picМесяц.Print 'Пустая строка
picМесяц.Print 'Пустая строка
'Печатаем названия (сокращенные) дней
недели
'с одним пробелом между ними
picМесяц.Print " ПН ВТ СР ЧТ ПТ СБ ВС"
picМесяц.Print 'Пустая строка
'Формируем строку — первый день месяца
ПервДень = "1 " + Месяц + ", " &
Год
'Определяем день недели этого дня
День = Weekday(ПервДень) — 1
picМесяц.Print Spc((День — 1) * 3);
'На каждый день отводим 3 позиции
For I = 1 To ЧислоДней(Месяц, Год)
picМесяц.Print Format(I, "@@@");
'Формат числа — 3 символа
'Проверяем, не наступил ли конец недели
If (День — 1 + I) Mod 7 = 0 Then
'Переход на новую строку
picМесяц.Print
End If
Next I
End Sub
Код для кнопки Очистить:
Private Sub cmdОчистить _Click()
'Очистить блок картинки
picМесяц.Cls
End Sub
Сохранение проекта
Создайте папку КАЛЕНДАРЬ и
сохраните в ней форму и проект под именами calendar.frm
и calendar.vbp.
Тестирование приложения
Запустите программу. Выберите месяц и
год, после чего щелкните на кнопке Показать —
результат должен быть аналогичен изображенному
на рис. 3.

Рис. 3
Проверьте работу программы на других
месяцах и годах, в т.ч. високосных.
Взгляд назад
Проверьте, что программа выполняет
все, что требуется. Нужны ли пользователю
какие-либо инструкции? Удобно ли расположены
элементы управления? При необходимости
повторите все шаги решения задачи.
Пояснения
1. Эта программа знакомит с элементом
управления ListBox (Список). Во время
разработки приложения его элементы списка не
могут быть заданы — они могут быть добавлены во
время выполнения программы. AddItems — это метод,
который добавляет пункты в список:
.AddItem "Апрель"
.AddItem "Май"
.AddItem "Июнь"
Оператор присоединения With … End With
используется в этой программе, чтобы упростить
код.
2. Использование элементов управления ListBox
и VScrollBar гарантирует, что пользователь введет
допустимые исходные данные.
3. У элемента управления ListBox есть
свойство ListIndex, которое указывает номер
выбранного элемента списка (нумерация элементов
начинается с 0). Поэтому в этой программе, когда
загружается форма, свойству lstМесяц.ListIndex присваивается
значение 0, в результате чего выбранным месяцем
становится Январь (в списке он выделен).
Когда элемент списка выбран, он
становится значением свойства Text элемента
управления ListBox, в нашем случае lstМесяц.Text. Например,
если lstМесяц.ListIndex имеет значение 2, то lstМесяц.Text =
"Март".
Кроме того, отдельные элементы списка
могут быть выбраны при использовании значения
свойства List. Например, lstMonth.List(2) имеет
значение Март, lstMonth.List(5)имеет значение Июнь.
4. Довольно трудно при печати
разместить числа месяца точно под названиями
соответствующих дней недели. Проще всего сделать
это, выбрав шрифт Courier New, который является так
называемым моноширинным шрифтом (каждый
символ такого шрифта имеет одинаковую ширину).
5. В этом примере при печати
используется функция Tab. Она определяет позицию
для печати очередного элемента. Например, в
результате выполнения оператора
Print Tab(5); "Имя"; Tab(15); "Адрес"
слово Имя будет напечатано начиная
с 5-й позиции, слово Адрес — с 15-й позиции.
6. ПервДень — строковая переменная,
значением которой является первый день того
месяца, который был выбран. Например: 1 июня 1954.
Это значение может быть интерпретировано
стандартной функцией Weekday, которая вычисляет,
каким днем недели является эта дата, и возвращает
целое число от 1 до 7 (от воскресенья до субботы —
для англоязычных календарей). В нашей стране
принято считать первым днем недели понедельник,
поэтому необходимо из возвращаемого функцией
Weekday числа вычесть 1:
День = Weekday(ПервДень) — 1
7. Обратите внимание, как “строится”
значение переменной ПервДень. Для “склейки”
двух строковых переменных применяется операция,
которую называют конкатенацией. В качестве
знака этой операции используется “+” или
“&”. Примеры:
ПервДень = "1 " + Месяц + ", " +
Год
ПервДень = "1 " & Месяц & ", "
& Год
8. Обратите внимание на условие,
которое определяет, достигнут ли конец недели4
If (День — 1 + I) Mod 7 = 0 Then
Проверьте это на следующем примере: 1
июня 1954 был вторник, поэтому День = 2; когда
переменная I станет равна 6, День – 1 + I
= 7, 7 Mod 7 = 0. Таким образом, условие верно, поэтому
выполняется следующая строка кода:
picМесяц.Print
— следующий символ будет печататься с
новой строки.
9. “Печатать” пробелы лучше всего с
помощью функции Spc.
10. Функция Format имеет много вариантов
для печати чисел, денежных форматов и дат.
Вариант, выбранный в этой программе, нужен для
того, чтобы убедиться, что число займет три
позиции независимо от того, состоит оно из одной
или из двух цифр. Формат ‘@@@’ заполняет позиции
справа налево, вставляя пробелы вместо
отсутствующих цифр. Благодаря этому числа месяца
стоят точно под названием дня недели. Обратите
внимание на точку с запятой (;) в конце строки
кода, которая нужна для того, чтобы каждый день
печатался в той же самой строке до тех пор, пока
условие (День – 1 + I) Mod 7 = 0 не выполнится и
не начнется следующая неделя.
Вопросы и задания для проверки знаний
1. Напишите строку кода, которая будет
добавлять имя “Иванов Петя” в список с именем lstУченики.
2. Каково будет значение lstМесяц.ListIndex
в этом примере программирования, когда в списке
будет выбран сентябрь?
3. Почему в этом примере
программирования выбран шрифт Courier New?
4. Что значит моноширинный шрифт?
5. Напишите оператор присваивания,
который будет “соединять” имя Николай,
отчество Иванович и фамилию Ветров, чтобы
получилось Ветров Николай Иванович.
Используйте символьные переменные Ф.И.О., Фамилия,
Имя и Отчество.
6. Объявлены переменные
Dim N1 As Integer, N2 As Integer
Dim S As String
Напишите оператор присваивания,
который присваивает переменной S результат
конкатенации значений N1, “ + ” и N2.
7. К сожалению, наш вечный календарь
недостаточно точен. Когда первый день месяца
приходится на воскресенье, программа работает
неправильно. Какие изменения необходимо сделать
в коде, чтобы это исправить? Внесите эти
изменения.
8. Разработайте программу, которая
будет переводить любое число от 1 до 99 в его
словесный эквивалент (см. рис. 4).

Рис. 4
9. Разработайте программу, которая
будет содержать список имен (в алфавитном
порядке) и печатать этот список, если потребуется
(см. рис. 5).

Рис. 5
Вам нужно будет использовать метод
RemoveItem, который удаляет пункты из списка.
Например, lstДрузья.RemoveItem 3 будет удалять
четвертый пункт из списка lstДрузья (вспомните,
что нумерация списка начинается с 0).
Свойство списка, характеризующее число
элементов в этом элементе управления, — ListCount.
Продолжение |