| Пособие-самоучитель on-line "Visual Basic с нуля" |
Глава 8. Объекты CheckButton, OptionButton и Frame. Операторы для переименования уничтожения и пр. файлов. Функция Dir. Объекты ComboBox и ListBox.
Скачать исходник программы "Тестер" | Дата создания 29.11.2004 {Автор 4us}

Снова становимся на тенистый путь программиста . Для логического завершения первой части, я решил в этой главе подобрать хвосты. Во-первых, о чем мы не говорили и что лежит прямо при загрузке VB. Какие объекты мы не затронули (конечно только пока из тех, которые стандартно лежат в окне Панели инструментов, то есть слева, где наши объекты формы). Вот на рисуночке я обвел их кружочками. Хотите поговорим об этом? Ну и ладно. Все равно поговорим.

Рисунок 16.

До фига получилось. Ну ничего. Это вобщем-то простые объекты, но в один пример запихнуть их все, пожалуй, не удасться.

Создадим новый exe-проект и положим на форму, например три флажка (CheckBox'а). Ну и вот, по умолчанию в квадратике нет ничего и главное значение этого объекта .Value равно 0 - Неотмечено. Когда мы щелкаем по флажку, то появляется галочка, и значение .Value становится равным 1-Отмечено. Bот и все. Есть еще и третье значение 2 - Выключено, но установить его щелканьем мышки не удасться. Надо либо в окне свойств задать значение, либо в коде написать
Check1.Value=2
при этом квадратик станет сереньким, типа выключился, но если по нему щелкнуть, то он опять примет значение включенного.

Аналогично работает и и радиокнопка (OptionButton) за исключением следующего. Первое: у OptionButton только два значения и принимают они "False" - выключено, точки в кружочке нет, и "True" - включено, точка есть. А второе, если вы на форму положите пять Check'ов, то вы можете включить сколько угодно из них, хоть три, хоть все пять. А вот Option можно включить только один. Если щелкнешь по другому, то включенный тут же выключится.
Кроме того, и у Check и у Option есть еще одно свойство Style. По умолчанию оно равно 0 - Standart. Но если его поставить в состояние 1- Graphical, то бац, твоя фигня с галочкой превращается по виду в кнопку. Внешне от кнопки Command она отличается тем, что в нажатом состоянии она показана, как нажатая. Ну и само собой свойство Caption позволяет Вам обзывать эти объекты, как угодно.

Далее объект Фрейм (Frame). Это как-бы окно, в которое можно запихивать флажки, радиокнопки, да что угодно. Но чтоб объект попал во Frame, надо его туда класть сразу. Если ты его создашь в форме вне фрейма, а потом перетащишь его во фрейм, то ничего не выйдет. Объект просто ляжет сверху. Ну и передвигая фрейм, ты сразу двигаешь и запихнутые туда объекты, что удобно. А если уничтожишь фрейм, то погибнут и все встроенные в него объекты. Вообще фреймами удобно делить форму на зоны. Кроме того, радиокнопки одного фрейма не связаны с радиокнопками другого или с внешними (на форме). Т.е. ты в каждом фрейме можешь создавать свой блок кнопок.

Программка-тест.
Сейчас мы напишем программку для тестов, где все это попробуем, а заодно потренируемся работать с текстовыми файлами, о чем говорилось в прошлой главе. Смысл программки в том, что мы готовим тест, например, психологический и на вопрос предлагаем испытуемому несколько ответов. По результатам теста выводим характеристику испытуемому.
Во-первых сделаем одну форму Form1 для создания контрольных вопросов, которую испытуемому видеть ни к чему - это форма для руководителя проекта тестирования. А вторая - Form2 - предлагается испытуемому для проведения теста.
Создадим новый exe-проект и на Form1 положим Text1 для занесения вопроса (не забудь его свойство Multiline поставить в True), Text2, Text3 и Text4 - для ответов, Text5, Text6, и Text7 для баллов по каждому ответу, кнопку Command1 для записи этого в файл и кнопки Command2 и Command3 для навигации по файлам (типа вверх-вниз). Я не стал использовать ScrollBar, чтобы не затемнять смысл программы. Поскольку мы еще не все познали-изучили (массивы или там файлы с прямым доступом), то будем записывать каждый вопрос в отдельный файл. Поэтому один Label1 надо положить сразу, он будет показывать номер вопроса, который будет и именем txt-файлов. А лучше сразу положить еще Label2 и Label3. У тебя должно получиться что-то типа рис.17

Рисунок 17.

Теперь убираем во всех Text'ах свойство Text (просто стираем в окне свойств), затем в свойстве Caption лейблов Label2 и Label3 пишем Ответы и Баллы соответственно. В свойствах Caption у кнопки Command1 пишем Сохранить вопрос, у кнопки Command2 - Назад, у кнопки Command3 - Вперед и изменяем их размеры соответственно надписи. Теперь пишем код в окне кода.

Перво-наперво, конечно Option Explicit, если вы не смогли установить VB, чтоб он прописывал это автоматом (я рассказывал как). Потом там - же, в области (General) - (Declarations) объявляем следующие переменные:

`Option Explicit``
` `'Для хранения номера вопроса (числовое, потому, что будем
'складывать и вычитать) и одновременно имя файла (строковое).
' Вот единственный случай использования типа Variant
Dim NomVopros As Variant
'и для каждого нашего текстбокса
Dim Vopros As String 'Text1-строковое, здесь пишем вопрос
Dim Otvet1 As String 'Text2-строковое- пишем возможный ответ №1
Dim Otvet2 As String 'Text3-строковое- пишем возможный ответ №2
Dim Otvet3 As String 'Text4-строковое- пишем возможный ответ №3
Dim Ball1 As Long 'Text5 -числовое - баллы к ответу №1
Dim Ball2 As Long 'Text6-числовое - баллы к ответу №2
Dim Ball3 As Long 'Text7-числовое - баллы к ответу №3`

Почему так? На фик нам эти переменные? Писали бы в файл и грузили бы сразу из TextBox'ов. А потому, во-первых, что из TextBox'ов все бы записывалось как текст (строка), а у нас переменные разных типов, а во-вторых, при считывании вообще возникла бы ошибка, потому что нельзя так. И вообще, лучше всегда использовать переменные, а не объекты. Далее объявим еще две переменные, одна просто для получения свободного номера файла

`Dim` `F As Long`

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

`Dim` `Flag As Boolean`

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

Функция DIR подробно.

Синтаксис ее такой:

Dir (Полный путь, атрибут)

Ну полный путь - это понятно, типа "c:\windows\system\хрень.dll". А атрибуты его это константы и могут принимать такие значения

Имя константы | Числовое значение константы | Тип файлов
vbNormal | 0 | обычные файлы
vbHidden | 2 | скрытые файлы
vbSystem | 4 | системные файлы
vbVolume | 8 | метка тома
vbDirectory | 16 | каталог (папка)

Если атрибут не ставить, то по умолчанию он равен 0 (обычный файл). Еще нам будет интересен атрибут = 16 (каталог, то бишь папка).
Причем все элементы функции Dir необязательны. Так как еe использовать?
Смысл ее работы в том, что она ищет файл, удовлетворяющий пути. Если она его находит, то возвращает его имя, если нет, то пустую строку (""). Используя это замечательное свойство, можно ее использовать следующим образом:

- Проверить, существует ли файл "c:\windows\system\хрень.dll"
If Dir("c:\windows\system\хрень.dll")<>"" Then Text1.Text="А я нашла файлик"
т.е. можно смело с этим файлом работать.

-Проверить, существует ли директория windows
If Dir("c:\windows",vbDirectory)<>"" Then Text1.Text="А я нашла папочку"
или (вместо константы vbDirectory можно поставить число 16
If Dir("c:\windows",16)<>"" Then Text1.Text="А я нашла папочку"
Это довольно-таки просто. А вот что бы найти все файлы в папке, узнать их имена, и т.п., надо написать такой код:
Для этого примера я предполагаю, что на форме есть кнопка Command1 и текстбокс Text1. Весь код пишется в процедуре кнопки.

`Private Sub` `Command1_Click()`

Объявим переменную, FileName как строковую. Мы будем присваивать ей имя файла (переменная локальная, работает только в этой процедуре)

`Dim` `FileName As String`

и очистим Text1 (на всякий случай)

`Text1.Text = ""`

Присвоим нашей переменной значение, которое вернет функция Dir. Обратите внимание, что имя файла состоит из звездочек. Это потому, что мы хотим получить имена всех существующих файлов, независимо от имени и расширения. Допустимо также использовать знак ? (например, если мы хотим получить имена всех файлов с расширение txt, имена которых одинаковы, кроме последнего знака (file1.txt, file2.txt... file9.txt) , можно написать "file?. txt"

`FileName = Dir("D:\MyPicture\Disk_001\*.*")`

Сейчас функция Dir сработала первый раз (по полному пути) и теперь знает, в какой директории мы ведем поиск. Далее проверяем, может в этой папке вообще файлов нет

`If` `FileName <> "" Then`

если наша переменная, которая должна была получить имя от функции Dir - не пустая, значит все в порядке, файлы есть. И теперь организовываем цикл Do...While, который будет выполнятся, пока функция Dir не вернет пустую строку (а это значит, что файлов, удовлетворяющих нашему пути "D:\MyPicture\Disk_001\*.*" нет.

`Do While FileName <> ""`

Теперь дописываем имя полученного файла в тектбокс Text1 (константу vbCrLf ставим, чтобы у нас каждое новое имя файла писалось с новой строки, если конечно свойство MultiLine текстбокса стоит в состоянии True)

`Text1.Text = Text1.Text & FileName & vbCrLf`

теперь нам в этом же цикле нужно снова запустить функцию Dir, на сей раз без аргументов, просто скобочки (а можно и вообще без них

`FileName = Dir``() ' или FileName = Dir`

Теперь закроем цикл, закроем условие If и закроем процедуру Command1_Click

`Loop
End If
End Sub`

Вот и все. Можете проверить.
Еще раз поясняю работу Dir для выборки группы файлов. Первый вызов функции имеет полный путь до файла и маску имени файла ( с использованием * и ? ). При этом функция возвращает первое попавшееся имя файла, удовлетворяющее маске. Второй и последующие вызовы - функция не имеет аргументов и возвращает имена файлов, удовлетворяющих маске в произвольном порядке. После того, как все имена файлов возвращены и в директории нет больше файлов с именами, удовлетворяющими нашей маске, функция Dir возвращает значение "пустая строка" (""). Это сигнал к тому, что пора прекратить вызовы функции Dir. Если снова вызвать функцию Dir без аргументов, то это вызовет ошибку выполнения. Вызывать функцию можно теперь по-новой , с полным путем до файла.
Поскольку мы не использовали второй аргумент "атрибут", то по умолчанию он равен 0, т.е. выбираются файлы. Если мы поставим атрибут 16 - папка, то это вовсе не значит, что функция Dir будет выбирать для нас только папки. Она выберет и папки и файлы, входящие в указанную нами в пути директорию. Есть прием, который позволяет отделить файлы и оставить только папки. Он приведен в Хелпе для пятого Бейсика.
Кроме того, поскольку Функция Dir возвращает файлы в произвольном порядке, то для достойного вывода списка файлов на экран, их надо отсортировать хотя бы в алфавитном порядке. О сортировке мы будем говорить, когда будем рассматривать массивы.

Совет: Прежде чем открывать файл, проверьте, существует и он, с помощью функции Dir. Это позволит избежать ненужных ошибок.
Поскольку мы уже научились просматривать имена файлов, логично будет упомянуть другие операции с файлами:

Копирование, уничтожение, переименование и прочие действия с папками и файлами.

- оператор Kill путь - уничтожает файл (или файлы, если используются подстановочные знаки * или ?) с диска (пример Kill "c:\mypicture\*.jpg")
- оператор FileCopy "копируемый файл", "новое имя копируемого файла" - копирует файл. Лучше писать полный путь в обоих аргументах. (например: FileCopy "c:\referat.txt", "c:\allreferats\referat4.txt"). Открытый (например оператором Open) файл скопировать нельзя. Это вызовет ошибку выполнения.
- оператор Name "староеимяфайла" As "новоеимяфайла" - переименовывает файл или каталог. При этом если указать разные пути, то файл перенесется под другим именем. А если пути одинаковые, а имена разные, то произойдет переименование файла. (пример: Name "c:\autoexe.bat" As "d:\myfile.bat")
- оператор RmDir "путь" - уничтожает существующую пустую папку (пример RmDir "c:\Programs\Project"). При попытке удалить непустую папку возникает ошибка. Внимание, если не указать полный путь, оператор удалит папку из текущего каталога (пример RmDir "PAPKA").
- оператор MkDir "путь" - создает новую папку (пример MkDir "c:\Programs\Project"). Если полный путь не указан, папка создается в текущем каталоге. (пример MkDir "Новый проект" ).
- оператор СhDir "путь" - изменяет текущий каталог (а не диск) на указываемый в пути.
- функция CurDir ("диск") - возвращает текущий диск. Аргумент диск необязательный.
- оператор ChDrive "диск" - изменяет текущий диск. Аргумент диск - обязательный, в нем используется только первый символ.

В принципе, здесь все просто, поэтому специальной программой я иллюстрировать это не буду.

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

Shell ("путь до файла программы", "вид окна, в котором откроется программа")

Путь - это понятно, а второй аргумент - константа, которая может принимать следующие значения:

Имя константы | Числовое значение константы | В каком окно откроется программа
vbHide | 0 | скрытое окно, фокус
vbNormalFocus | 1 | свой размер, фокус
vbMinimizedFocus | 2 | в виде значка в контрольной панели, фокус
vbMaximizedFocus | 3 | в полный экран с фокусом
vbNormalNoFocus | 4 | свой размер без фокуса
vbMinimizedNoFocus | 6 | в виде значка в контрольной панель, без фокуса

Пример использования:ProgGO = Shell("C:\Program Files\BANDIT.EXE", 1) запускает программу "Однорукий бандит" с тем размером экрана, которая она имеет. Фокус будет на окне программы. В переменную, которую я назвал, например, ProgGO (ее надо объявить Dim ProgGo) возвращается идентификационный номер запущеной программы. А если программу запустить не удалось, возникает ошибка.

Извини за долгое оступление, но я посчитал своим долгом вывалить все это на тебя. Хоть и не сложно, но это понадобиться. Теперь, наконец, вернемся к нашей программе-тесту. Мы уже объявили все переменные, теперь сделаем собственную процедуру, которая будет грузить вопросы, ответы и баллы в форму. Назовем ее Loading().

`Private Sub` `Loading()`

Первым делом, конечно зададим имя формы, чтоб красиво было.

`Form1.Caption = "Запись теста - только для администратора теста"`

Поскольку мы к этой процедуре будем обращаться неоднократно и переменные могут хранить старые значения, мы очистим их:

`Vopros = ""
Otvet1 = ""
Otvet2 = ""
Otvet3 = ""
Ball1 = 0
Ball2 = 0
Ball3 = 0`

Теперь нам надо загрузить данные из файла вопросника. Для этого нам надо открыть файл с именем "номер вопроса.txt". Номер вопроса должен храниться в переменной NomVopros. Мы при загрузке формы присвоим ей значение "1", чтобы сначала попробовать загрузить файл с первым вопросом.
Прежде, чем открывать файл, надо проверить, существует ли он. Возможно это начало работы с тестом, и никаких вопросов просто не существует. Делаем это с помощью функции Dir, о которой мы так много говорили (причем ищем все в текущем каталоге - App.Path )

`If` `Dir(App.Path & "\" & NomVopros & ".txt") <> "" Then`

и если у нас файл существует (Dir - не пустая строка), тогда определяем свободный номер файла и открываем его

`F = FreeFile
Open App.Path & "\" & NomVopros & ".txt" For Input As #F`

Теперь с помощью оператора Input# считываем данные (я использовал три оператора только ради удобства чтения кода) и не забываем закрыть файл.

`Input``#F, Vopros
Input #F, Otvet1, Otvet2, Otvet3
Input #F, Ball1, Ball2, Ball3
Close #F`

В другой ветви оператора If (когда файла не существует) мы присваиваем булевой переменной Flag значение True

`Else
` `Flag = True
End If`

Переменная Flag служит нам индикатором, существует ли текущий файл (Flag=False), или еще нет (Flag=True). Больше мы в этой ветви цикла If ничего не делаем, потому. что открывать нечего. Но, после цикла, чтобы наши данные отобразились в форме, мы Текстбоксам присваиваем соответствующие значения переменных, независимо от того, пусты они или нет. Пользователь должен видеть реальную картину.

`Text1.Text = Vopros
Text2.Text = Otvet1
Text3.Text = Otvet2
Text4.Text = Otvet3
Text5.Text = Ball1
Text6.Text = Ball2
Text7.Text = Ball3`

Конец процедуры

`End Sub`

Теперь переходим к процедуре Form_Load. Что ж мы делаем при загрузке нашей формы Form1?

`Private Sub` `Form_Load()`

Присваиваем значение переменной NomVopros единицу (мы же хотим начинать с первого вопроса) и устанавливаем значение нашего флага в значение False. Изначально мы предполагаем, что файл с номером вопроса 1 существует:

`NomVopros = "1"
Flag = False`

Выводим в Label1 для пользователя номер обрабатываемого вопроса

`Label1.Caption = "Вопрос № " & NomVopros`

запускаем нашу процедуру загрузки файла Loading и конец процедуре Form_Load

`Loading
End Sub`

Теперь создаем процедуру для кнопки Command1 - это просто запись в файл с помощью оператора Write#. Только перед записью мы нашим переменным присвоим текущие значения Текстбоксов

`Private Sub` `Command1_Click()
Vopros = Text1.Text
Otvet1 = Text2.Text
Otvet2 = Text3.Text
Otvet3 = Text4.Text
Ball1 = Text5.Text
Ball2 = Text6.Text
Ball3 = Text7.Text`

ну и открываем и записываем файл под именем "номер текущего вопроса.txt"

`F = FreeFile
Open App.Path & "\" & NomVopros & ".txt" For Output As #F
Write #F, Vopros
Write #F, Otvet1, Otvet2, Otvet3
Write #F, Ball1, Ball2, Ball3
Close #F`

Поскольку мы файл записали, значит он существует, устанавливаем наш флаг в положение False и конец процедуре.

`Flag = False
End Sub`

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

`Private Sub` `Command2_Click()
If NomVopros > 1 Then
NomVopros = NomVopros - 1
Label1.Caption = "Вопрос № " & NomVopros
Loading
End If
End Sub`

А вот с другой кнопкой Command3 дело обстоит несколько сложнее. Нам нужно, чтоб мы двигались вперед до тех пор, пока не дойдем до первого несуществующего файла (нам же нужно создавать новые впросы для тестирования) и на нем стоп! Для этого мы проверяем выполнение двух условий:
первое - хотим ли мы перейти к существующему файлу, или этот файл еще не создан? Это просто проверяется функцией Dir. Если мы просто переходим с последнего файла на несуществующий - это пожалуйста, а вот если мы уже на несуществующем и пытаемся двигаться дальше, то этого допустить никак нельзя, поэтому
второе - вот настал час переменной Flag. Так вот ее состояние таково, что показывает, на каком файле мы находимся перед переходом. Если Flag=False, значит мы стоим на нормальном файле и к несуществующему перейти вполне можно и мы увиличиваем на единицу номер файла. А вот если Flag=True, то значит мы уже достигли предела и двигаться дальше нельзя. Вот это код:

`Private Sub` `Command3_Click()
If Dir(App.Path & "\" & NomVopros & ".txt") = "" And Flag = True Then
Exit Sub
Else
NomVopros = NomVopros + 1
Loading
End If
Label1.Caption = "Вопрос № " & NomVopros
End Sub`

Здесь мы используем оператор Exit Sub, который позволит нам выйти из процедуры, не выполняя ее до конца. Хочу обратить твое внимание, что в коде программы в трех местах встречается одна и та же строка Label1.Caption = "Вопрос № " & NomVopros. Это недопустимая халатность. На работоспособности программы это, конечно не скажется, но с точки зрения программирования, каждая лишняя строчка (особенно если их тысячи) - это смерть разрабатчикам, т.е. нам. Попробуйте убрать ее и поставить в одном месте, где бы она "работала за троих". В исходнике это сделано. Далее для красоты ты можешь надписи на кнопках Command2 и Command3 заменить стрелочками. Я вот нарисовал их просто в Paint'e. Получилось два маленьких bmp-файла Up.bmp и Down.bmp. Чтобы поставит их в кнопку нужно свойство кнопки Style в состояние 1 - Graphical, очистить свойство Caption и в свойстве Picture нажать на кнопочку с тремя точечками. У тебя появиться окно "загрузить рисунок", где можно благополучно выбрать графический файлик. Это файлик сохранится в твоей программе и таскать его за собой больше не надо, но у меня в исходнике они лежат, как бы для примера.

Ну вот, с первой частью программы мы закончили. А теперь неплохо-бы сделать форму собственно для тестирования. Для этого в нашу программу надо добавить еще одну форму. Вверху общего окна VB надо нажать на кнопку со словом Проект и в выпавшем меню кликнуть по первой строке "Добавить форму". Тут же откроется окно "Добавить форму" и первая картинка называется "Форма". Выдели ее, если она не выделена и нажми кнопку в этом же окне "Открыть" (или там Open). И хрясть, перед вами новая форма Form2, ну точно такая же как и старая.

Сделаем все почти по аналогии с первой формой.

Кладем на Form2, Label1, Text1, Command1 и Frame1. После этого, сразу во Frame1, а не на форму кладем три радиокнопки Option1, Option2 и Option3. Вот и готово. Кнопка Command1 будет называться " Ответить". Теперь объявляем переменные, аналогичные первой форме

`Option Explicit
Dim` `NomVopros As Variant
Dim Vopros As String
Dim Otvet1 As String
Dim Otvet2 As String
Dim Otvet3 As String
Dim Ball1 As Long
Dim Ball2 As Long
Dim Ball3 As Long
Dim F As Long`

плюс еще SumAns для суммирования баллов

`Dim` `SumAns As Long`

Создаем процедуру Loading, почти такую же, как и в первой форме, только ответы выводим в названия радиокнопок, а баллы нам вообше выводить не надо. И устанавливаем первую радиокнопку в положение "включено", иначе, если все кнопки будут выключены, пользователь может нажать кнопку "Ответить" , не выбрав варианта ответа.

`Private Sub` `Loading()
Option1.Value = True ' первая радиокнопка включена
Vopros = ""
Otvet1 = ""
Otvet2 = ""
Otvet3 = ""
Ball1 = 0
Ball2 = 0
Ball3 = 0
If Dir(App.Path & "\" & NomVopros & ".txt") <> "" Then
F = FreeFile
Open App.Path & "\" & NomVopros & ".txt" For Input As #F
Input #F, Vopros
Input #F, Otvet1, Otvet2, Otvet3
Input #F, Ball1, Ball2, Ball3
Close #F
Else
End If`

`Option1.Caption = Otvet1
Option2.Caption = Otvet2
Option3.Caption = Otvet3
Text1.Text = Vopros
Label1.Caption = "Вопрос № " & NomVopros
End Sub`

В процедуре загрузки формы задаем название формы

`Private Sub` `Form_Load()
Form2.Caption = "Тестирование"`

обнуляем на всякий случай сумматор ответов

`SumAns = 0`

и далее как в первой форме

`NomVopros = "1"
Loading
End Sub`

Теперь код кнопки "Ответить"

`Private Sub Command1_Click()`

Проверяем, какая радиокнопка нажата, и в зависимости от этого увеличиваем сумматор на количество баллов ответа

`If` `Option1.Value = True Then SumAns = SumAns + Ball1
If Option2.Value = True Then SumAns = SumAns + Ball2
If Option3.Value = True Then SumAns = SumAns + Ball3`

увеличиваем номер вопроса на один и проверяем, существует ли такой файл

`NomVopros = NomVopros + 1
If Dir(App.Path & "\" & NomVopros & ".txt") = "" Then`

если не существует, заканчиваем тест, находим среднее арифметическое и в зависимости от него выдаем сообщение в Text1 с помощью вложенного условия

`Text1.Text = "Тест окончен"
If SumAns / (NomVopros - 1) <= 1 Then
Text1.Text = Text1.Text & " Вы злой как собака"
ElseIf SumAns / (NomVopros - 1) > 1 And SumAns / (NomVopros - 1) <= 2 Then
Text1.Text = Text1.Text & " Бывают и добрее"
Else
Text1.Text = Text1.Text & " Вы сама доброта, таких не бывает"
End If`

Если есть файл, переходим к процедуре загрузки Loading и конец процедуре

`Else``
Loading
End If
End Sub`

Вот, практически и все. Только для редактирования вопросов надо иметь возможность тайно заходить на первую форму. Для этого я использовал два клика по TextBox'у

`Private Sub` `Text1_DblClick()
Form1.Show
End Sub`

И последнее. Поскольку первой (по умолчанию)грузиться должна Form2, войдем в меню Проект вверху окна VB и в выпавшем списке кликнем по последней строке "Проект1 Свойства". У нас откроется окно "Свойства проекта". На вкладке "Главное" в поле "Объект запуска" выберем Form2. Готово. Сохраняем проект. Исходник можно скачать вверху страницы.

Объекты ComboBox и ListBox.

Ну и в конце главы поговорим еще об объектах.
Два объекта ComboBox и ListBox очень похожи. Основные различия их в следующем: ComboBox выполнен в виде выпадающего списка и пользователь может добавлять в него строки, а ListBox похож на TextBox, если все строки не вмещаются, включаются полосы прокрутки. Основные методы у них следующие:
.AddItem - позволяет добавлять пункты (строки)
.RemoveItem - позволяет удалять строки
А основные свойства это:
.List(n) - позволяет ввести или вывести содержимое n-ой строки (пункта)
.ListCount - позволяет узнать количество строк (пунктов в объекте)
.ListIndex - позволяет вывести номер строки пункта, или перейти к строке с эти номером. Для ComboBox'a пустая строка имеет номер -1 (минус 1), а строки списка нумеруются от 0 и далее, поэтому количество строк всегда на 1 больше, чем номер последней строки. В ListBox'e нет строки -1 (минус 1).
.Text - позволяет вывести содержимое стоки, например в TextBox

Исходя из этого, и преполагая, что в нашем проекте на форме Form1 лежат Text1, Command1, Combo1, List1, то
вот пример кое-каких действий, которые мы можем совершить с ComboBox или ListBox

- добавить строку (пункт)
`Combo1.AddItem "Нулевая строка" ' добавляет строку номером (ListIndex) 0 (потому-что первая)
Combo1.AddItem "Вася" ' добавляет строку номером (ListIndex) 1 (потому-что вторая)
List1.AddItem "Нулевая строка"`
Другой путь - это войти в свойство .List в окне свойств, щелкнуть по свойству и выпавшем окне и дописывать строки в ручную, но мне представляется это не решением вопроса.

- удалить строку (пункт)
`Combo1.RemoveItem 0` `или ' удаляет строку под номером (ListIndex) 0
List1.RemoveItem 0`

- узнать (например вывести в TextBox) количество строк
`Text1.Text = Combo1.ListCount
Text1.Text = List1.ListCount`

- перейти к третьей строке
`Combo1.ListIndex = 2
List1.ListIndex = 2`

- вывести строку в TextBox
`Text1.Text = Combo1.Text 'выводит строку, по которой щелкнули мыщью
Text1.Text = List1.Text
Text1.Text = Combo1.List(3) 'выводит четвертую строку
Text1.Text = List1.List(3)`

- позволить пользователю дописать новую строку (только в ComboBox)
Это можно реализовать следующим образом. При загрузке пустая строка (ее индекс -1) пустая. В нее пользователь и пишет содержимое строки. Но оно не сохраниться. Поэтому, для сохранения новой строки можно использовать например, командную кнопку Command1. Тогда ее процедура будет выглядеть так

`Private Sub` `Command1_Click()
Combo1.AddItem Combo1.Text
End Sub`

Кроме того в окне свойств у этих объектов можно поставить свойство .Sorted в положение True. Тогда строки отсортируются в порядке возростания.
Ну вот про эти два объекта пока все.

Что касается графических объектов, то я упомяну их только для очистки совести. Нарисовать квадратик с помощью объекта Shape или линию с помощью объекта Line, по-моему может каждый и без особых инструкций.

Что касается объекта OLE, то это контейнер, который позволяет вставлять в форму различные объекты, например avi-файлы, картинки и т.п. Это достаточно капризный и кривой объект. В настоящий момент его подробное исследование нам совершенно ни к чему, есть задачи по-важнее.

Об объекте Data скажу следующее. Это один из объектов, который позволяет работать с существующей базой данных, создавать, удалять, сортировать и т.п. записи. Но изучение этого объекта довольно серьезная задача. Мы вернемся к ней позже. Вообще, перед этим хорошо-бы познакомится с Access'ом и сделать с помощью него хотя-бы одну простенькую базу.

Copyright © 2004 4us