Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Курсововой проект.doc
Скачиваний:
11
Добавлен:
08.12.2018
Размер:
1.02 Mб
Скачать
    1. Программная реализация

Итак, перейдем к реализации программы.

За главное окно отвечает модуль MainForm. Для упрощения кода и наглядности для данных используется отдельная структура. Для получения пути к файлам используются компоненты OpenFileDialog и SaveFileDialog, так как они обладают наибольшей простотой. При их создании используется конструктор.

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

С помощью процедуры Update() мы сразу загружаем в память ресурсы нужные для работы компонента WebBrowser. Благодаря этому убирается “зависание” при первом открытии формы Reader.

Код модуля приведен в листинге 1.

  1. Модуль MainForm

'Для работы с файлами нам потребуется импортировать следующий модуль

Imports System.IO

Public Class MainForm

'Объявляем запись, в которой будут хранится все данные программы

Structure TData

'Информация для тестирования

Structure TDataTest

Enum TQuestionType 'Для отображения вопросов используется:

std = 0 'текстовое поле и изображение

End Enum

Structure TQuestion 'Один вопрос программно это:

Dim Question As String 'текст

Dim Type As TQuestionType 'тип вопроса

Dim Answers As String() 'массив вопросов

Dim Opt As String() 'массив дополнительных опций

Dim Ball As Double 'балл за вопрос

Dim Image As Bitmap 'рисунок

End Structure

Dim Name, Desc As String 'Название и информация для теста

Dim nQ, Time As Integer 'Кол-во вопросов и время для теста

Dim Questions As TQuestion() 'Массив вопросов

End Structure

'Далее описание теоретической базы

Structure TDataTheory

Dim Title, Desc As String 'Название и информация

Dim FilePath As String 'Путь к корневому файлу .html

Dim Weight As String 'Объем

End Structure

'Описание статистики

Structure TStat

Dim Right, Wrong, NoTime, Time As Integer

Dim balls As Double

Dim TestName, Student As String

End Structure

Dim Stat As TStat

Dim Test As TDataTest

Dim Theory As TDataTheory

End Structure

'Объявление переменных

Public Data As TData

'Функция, которая возвращает true в случае успешного открытия файла. В качестве параметра type передается тип открываемого файла. “0” – файл “.test”, “1” – файл “.theory”, “2” – файл “.stat”

Private Function OpenFile(ByVal f As String, ByVal type As Integer) As Boolean

Dim fFile As FileStream 'универсальный файловый дескриптор

Dim Reader As StreamReader 'инструмент для чтения файла

Dim Backup As TData 'в случае ошибки возвращает нач. значения

Dim Flag As String 'флаг, используемый в циклах

Backup = Data

OpenFile = True

Try 'ручное управление обработкой ошибок

If type = 0 Then 'открываем файл “.test”

fFile = New FileStream(f, FileMode.Open)

Reader = New StreamReader(fFile)

ReDim Data.Test.Questions(0 To 0) 'считываем информацию

Data.Test.Name = Reader.ReadLine

Data.Test.Desc = Reader.ReadLine

Data.Test.Time = Val(Reader.ReadLine)

While Not (Reader.EndOfStream)

Data.Test.Questions(Data.Test.Questions.Length - 1).Question = Reader.ReadLine.Replace("|", Chr(13))

Data.Test.Questions(Data.Test.Questions.Length - 1).Answers = Reader.ReadLine.Split("|")

Data.Test.Questions(Data.Test.Questions.Length - 1).Type = Val(Reader.ReadLine)

Flag = Reader.ReadLine

If Flag <> "*" Then

Data.Test.Questions(Data.Test.Questions.Length - 1).Image = Image.FromFile(BDir + Flag)

End If

Data.Test.Questions(Data.Test.Questions.Length - 1).Ball = Val(Reader.ReadLine)

Data.Test.Questions(Data.Test.Questions.Length - 1).Opt = Reader.ReadLine.Split("|")

If Data.Test.Questions(Data.Test.Questions.Length - 1).Opt(0) = "*" Then

Data.Test.Questions(Data.Test.Questions.Length - 1).Opt = Nothing

End If

‘лишний элемент в массиве нужно удалить

If Not (Reader.EndOfStream) Then

ReDim Preserve Data.Test.Questions(0 To Data.Test.Questions.Length)

End If

End While

ElseIf type = 1 Then 'открываем файл “.theory”

fFile = New FileStream(f, FileMode.Open)

Reader = New StreamReader(fFile)

Data.Theory.Title = Reader.ReadLine

Data.Theory.Desc = Reader.ReadLine

Data.Theory.Weight = Reader.ReadLine

Data.Theory.FilePath = BDir + Reader.ReadLine

ElseIf type = 2 Then 'открываем файл “.stat”

fFile = New FileStream(f, FileMode.Open)

Reader = New StreamReader(fFile)

Data.Stat.TestName = Reader.ReadLine

Data.Stat.Student = Reader.ReadLine

Data.Stat.Wrong = Reader.ReadLine

Data.Stat.Right = Reader.ReadLine

Data.Stat.NoTime = Reader.ReadLine

Data.Stat.Time = Reader.ReadLine

Data.Stat.balls = Reader.ReadLine

End If

fFile.Close()

Reader.Close()

Catch

'В случае ошибки закрываем дескрипторы, возвращаем все на свои места.

Data = Backup

OpenFile = False

fFile.Close()

Reader.Close()

End Try

End Function

'Кнопка “Загрузить тест”

Private Sub Button5_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button5.Click

OpenFileDialog.Reset()

OpenFileDialog.Filter = "Тестовые задания|*.test"

OpenFileDialog.ShowDialog()

If OpenFileDialog.FileName = "" Then

Exit Sub

End If

If OpenFile(OpenFileDialog.FileName, 0) Then

Label3.Text = "Название теста:" + Chr(13) + Data.Test.Name + Chr(13)

Label3.Text += "Описание теста:" + Chr(13) + Data.Test.Desc + Chr(13)

Label3.Text += "Количество вопросов:" + Data.Test.Questions.Length.ToString + Chr(13)

Button1.Enabled = True

Else

MessageBox.Show("Ошибка открытия файла.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error)

End If

Button1.Focus()

End Sub

'Кнопка “Загрузить теорию”

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

OpenFileDialog.Reset()

OpenFileDialog.Filter = "Документы|*.theory"

OpenFileDialog.ShowDialog()

If OpenFileDialog.FileName = "" Then

Exit Sub

End If

If OpenFile(OpenFileDialog.FileName, 1) Then

Label2.Text = "Название:" + Chr(13) + Data.Theory.Title + Chr(13)

Label2.Text += "Описание:" + Chr(13) + Data.Theory.Desc + Chr(13)

Label2.Text += "Объем:" + Data.Theory.Weight.ToString

Button6.Enabled = True

Else

MessageBox.Show("Ошибка открытия файла.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error)

End If

Button6.Focus()

End Sub

'Процедура отображения результатов тестирования

Sub ShowStat()

Label1.Text = "Название теста:" + Chr(13) + Data.Stat.TestName + Chr(13)

Label1.Text += "Студент:" + Chr(13) + Data.Stat.Student + Chr(13)

Label1.Text += "Всего вопросов: " + (Data.Stat.Right + Data.Stat.Wrong + Data.Stat.NoTime).ToString + Chr(13)

Label1.Text += "Верно: " + Data.Stat.Right.ToString + Chr(13)

Label1.Text += "Неверно: " + Data.Stat.Wrong.ToString + Chr(13)

Label1.Text += "Без ответа: " + Data.Stat.NoTime.ToString + Chr(13)

Label1.Text += "Коэффициент: " + (Math.Round(Data.Stat.Right / (Data.Stat.Right + Data.Stat.Wrong + Data.Stat.NoTime), 2) * 100).ToString + "%" + Chr(13)

Label1.Text += "Затраченное время: " + Math.Truncate(Data.Stat.Time / 60).ToString + " м. " + (Data.Stat.Time Mod 60).ToString + " с." + Chr(13)

Label1.Text += "Оценка: " + Math.Round(Data.Stat.balls).ToString + Chr(13)

End Sub

'Кнопка “Начать тестирование”

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Test.Show()

Me.Visible = False

End Sub

'Кнопка “Читать теорию”

Private Sub Button6_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button6.Click

Reader.Show()

Me.Visible = False

End Sub

'Загрузка формы

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

Reader.Update() 'данный код позволяет предварительно загрузить библиотеки для работы компонента WebBrowser

End Sub

'Кнопка “Сохранить результаты”

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

Dim dlg As SaveFileDialog = New SaveFileDialog()

dlg.CheckPathExists = True

dlg.AddExtension = True

dlg.Filter = "Результаты|*.stat"

'dlg.FileName = TimeOfDay.ToString.Replace(".", "-").Replace(" ", "_").Replace(":", "-") + ".stat"

dlg.FileName = TimeOfDay.Ticks.ToString + "_" + Data.Stat.Student + "_" + ".stat"

Dim res As DialogResult = dlg.ShowDialog()

If res = Windows.Forms.DialogResult.Cancel Then

Exit Sub

End If

Dim f As FileStream

f = New FileStream(dlg.FileName, FileMode.CreateNew)

Dim stw As IO.StreamWriter

stw = New IO.StreamWriter(f)

stw.WriteLine(Data.Stat.TestName)

stw.WriteLine(Data.Stat.Student)

stw.WriteLine(Data.Stat.Wrong)

stw.WriteLine(Data.Stat.Right)

stw.WriteLine(Data.Stat.NoTime)

stw.WriteLine(Data.Stat.Time)

stw.WriteLine(Data.Stat.balls)

stw.Close()

f.Close()

End Sub

'Кнопка “Просмотреть результаты”

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

OpenFileDialog.Reset()

OpenFileDialog.Filter = "Результаты|*.stat"

OpenFileDialog.ShowDialog()

If OpenFileDialog.FileName = "" Then

Exit Sub

End If

If OpenFile(OpenFileDialog.FileName, 2) Then

ShowStat()

Else

MessageBox.Show("Ошибка открытия файла.", "Ошибка", MessageBoxButtons.OK, MessageBoxIcon.Error)

End If

Button1.Focus()

End Sub

End Class

Далее, для модуля Reader используется компонент WebBrowser, который обладает большими преимуществами в отношении просмотра контента, если учесть, что все отображение документов он, буквально, берет на себя. Нам лишь остается вызвать команды встроенные в его класс. Поэтому он используется в модуле (листинг 2). Код модуля приведен в листинге 2.

  1. Модуль Reader

Public Class Reader

'Загрузка формы

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

Me.Text = MainForm.Data.Theory.Title

WebBrowser1.Navigate(MainForm.Data.Theory.FilePath)

End Sub

'Закрытие формы

Private Sub Reader_FormClosed(ByVal sender As System.Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles MyBase.FormClosed

If Test.Visible <> True Then

MainForm.Visible = True

End If

End Sub

'Кнопка “начать тестирование”

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

Test.Show()

Me.Close()

End Sub

'Кнопка “закончить”

Private Sub Button4_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button4.Click

Me.Close()

End Sub

'Кнопка “Главная”

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

WebBrowser1.Navigate(MainForm.Data.Theory.FilePath)

End Sub

'Кнопка “Назад”

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

WebBrowser1.GoBack()

End Sub

'Для большей “встроенности” компонента фоновый цвет документа делается таким же как на форме

Private Sub WebBrowser1_DocumentCompleted(ByVal sender As System.Object, ByVal e As System.Windows.Forms.WebBrowserDocumentCompletedEventArgs) Handles WebBrowser1.DocumentCompleted

WebBrowser1.Document.BackColor = MainForm.BackColor

End Sub

End Class

В модуле Test структура TBase используется для хранения элементов размещенных на форме. Обращаясь к переменной Base, производной от TBase, мы можем динамически их изменять. Процедура Clear_Base() используется для очистки значений занесенных в переменную, а в процедуре Show_Q() как раз реализовано динамическое размещение элементов на форме..

Для удобства, программа сделана так, что пройти тестирование можно при помощи лишь одной клавиатуры. Для этого используется обработка нажатия клавиши Enter и метод Focus(). Также используется шрифт размера 14pt, вместо стандартного 12pt, что позволяет быстрее прочитать и понять вопрос.

Можно выводить не только текстовую информацию, но также в дополнительном изображении можно представить любую формулу, таблицу, рисунок и т. п.

Из особенностей программы можно отметить, что она использует так называемую “очередь вопросов”, что позволяет отправлять пропущенные вопросы в конец и не заботиться о порядке их следования. Код модуля приведен в листинге 3.

  1. Модуль Test

Public Class Test

Dim Turn As Integer() 'порядок вопросов

Dim Current As Integer = 0 'текущий вопрос

Dim LastTime As Integer 'оставшееся время

Dim CAnswers As String() 'ответы

Dim f As Boolean = True 'флаг

Structure TBase 'используется для генерации

Dim qLabel As Label() 'динамического отображения вопросов

Dim qImage As PictureBox()

Dim qRadio As RadioButton()

End Structure

Dim Base As TBase

'Очищает окно

Private Sub Clear_Base(ByRef first As Boolean)

If Not (first) Then

For Each i In Base.qImage

Me.Controls.Remove(i)

Next

For Each i In Base.qRadio

Me.Controls.Remove(i)

Next

For Each i In Base.qLabel

Me.Controls.Remove(i)

Next

End If

ReDim Base.qImage(0 To 0)

ReDim Base.qLabel(0 To 0)

ReDim Base.qRadio(0 To 0)

End Sub

'Обновление информационного поля

Private Sub Reflesh_Info()

Info.Text = "Осталось вопросов: " + (Turn.Length - Current - 2).ToString + "; Осталось времени: " + (Math.Truncate(LastTime / 60)).ToString + " м. " + (LastTime Mod 60).ToString + " с."

End Sub

'Процедура, отображающая вопрос

Private Sub Show_Q(ByVal nQ As Integer)

Const border = 10 'граница, вдоль которой расположены элементы

Clear_Base(False)

'если тип вопроса “std”, то выводим одно label и picture box

If MainForm.Data.Test.Questions(nQ).Type = MainForm.TData.TDataTest.TQuestionType.std Then

Base.qLabel(0) = New Label

Me.Controls.Add(Base.qLabel(0))

Base.qLabel(0).Top = border

Base.qLabel(0).Left = border

Base.qLabel(0).Text = MainForm.Data.Test.Questions(nQ).Question

Base.qLabel(0).Width = Me.Width - border * 2 - 5

Base.qLabel(0).Height = 380

Base.qLabel(0).Font = New Font(Me.Font.FontFamily, 14, FontStyle.Regular)

If Not (MainForm.Data.Test.Questions(nQ).Image Is Nothing) Then

Base.qImage(0) = New PictureBox

Me.Controls.Add(Base.qImage(0))

Base.qImage(0).BackColor = Color.Transparent

Base.qImage(0).Image = MainForm.Data.Test.Questions(nQ).Image

Base.qImage(0).Width = Base.qLabel(0).Width

Base.qLabel(0).SendToBack()

Base.qImage(0).Left = Base.qLabel(0).Left + 1

Base.qImage(0).Height = 200

Base.qImage(0).Top = Base.qLabel(0).Top + Graphics.FromHwnd(Base.qLabel(0).Handle).MeasureString(MainForm.Data.Test.Questions(nQ).Question, Base.qLabel(0).Font, Base.qLabel(0).Width).Height

Base.qImage(0).Visible = True

End If

End If

'Подведение статистики. В st передается ФИО студента и номер группы

Private Sub Collect_Info(ByVal st As String)

Dim i As Integer

Dim helpa As String()

'Очищаем предыдущую статистику

MainForm.Data.Stat.Right = 0

MainForm.Data.Stat.Wrong = 0

MainForm.Data.Stat.NoTime = 0

MainForm.Data.Stat.balls = 0

MainForm.Data.Stat.Student = st

MainForm.Data.Stat.TestName = MainForm.Data.Test.Name

MainForm.Data.Stat.Time = MainForm.Data.Test.Time – LastTime

'Сверяем ответы

For i = 0 To CAnswers.Length - 1

ReDim helpa(0 To MainForm.Data.Test.Questions(i).Answers.Length)

helpa = MainForm.Data.Test.Questions(i).Answers

If (MainForm.Data.Test.Questions(i).Answers(0) = CAnswers(i)) Or (Array.IndexOf(MainForm.Data.Test.Questions(i).Answers, CAnswers(i)) > 0) Then

MainForm.Data.Stat.Right += 1

MainForm.Data.Stat.balls += MainForm.Data.Test.Questions(i).Ball

Else

MainForm.Data.Stat.Wrong += 1

End If

Next i

'Подсчитываем время

MainForm.Data.Stat.NoTime = MainForm.Data.Test.Questions.Length - MainForm.Data.Stat.Right - MainForm.Data.Stat.Wrong

End Sub

'Загрузка формы, где производится задание начальных значений

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

Dim i As Integer

ReDim Turn(0 To 0)

For i = 0 To MainForm.Data.Test.Questions.Length - 1

Turn(i) = i

ReDim Preserve Turn(0 To Turn.Length)

Next i

ReDim CAnswers(0 To Turn.Length - 2)

Clear_Base(True)

Text = MainForm.Data.Test.Name

LastTime = MainForm.Data.Test.Time

Reflesh_Info()

Show_Q(Turn(Current))

TextBox1.SelectAll()

Timer1.Enabled = True

End Sub

'Нажатие кнопки “Пропустить”

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

Turn(Turn.Length - 1) = Turn(Current)

ReDim Preserve Turn(0 To Turn.Length)

Current += 1

Show_Q(Turn(Current))

End Sub

'Процедура завершения теста. В качестве параметра abort передается значение, прошел ли студент тестирование или решил его прервать

Private Sub End_Test(ByVal abort As Boolean)

Timer1.Enabled = False

If abort Then

MainForm.Visible = True

Me.Close()

Exit Sub

End If

Dim st As String

Do

st = InputBox("Введите ФИО и номер группы", "Вы завершили тест!", "")

Loop Until st <> ""

Collect_Info(st)

MainForm.Visible = True

MainForm.ShowStat()

MainForm.Button4.Enabled = True

MainForm.Button4.Focus()

Me.Close()

End Sub

'Нажатие на кнопку “Ответить”

Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

CAnswers(Turn(Current)) = TextBox1.Text

If Current <> Turn.Length - 2 Then

TextBox1.Text = "Введите ответ"

TextBox1.Focus()

TextBox1.SelectAll()

Current += 1

Show_Q(Turn(Current))

Reflesh_Info()

If Current = Turn.Length - 2 Then

Button1.Enabled = False

End If

Else

End_Test(False)

End If

End Sub

'Отсчет времени. После того как LastTime окажется равным 0, тест завершается

Private Sub Timer1_Tick(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Timer1.Tick

If f Then 'первый запуск таймера

TextBox1.Focus()

TextBox1.SelectAll()

Timer1.Interval = 1000

f = False

End If

LastTime -= 1

Reflesh_Info()

If LastTime = 0 Then

End_Test(False)

End If

End Sub

'Нажатие на кнопку “Завершить тест”

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

If MessageBox.Show("Вы уверены, что хотите завершить тест?", "Внимание!", MessageBoxButtons.YesNo) = Windows.Forms.DialogResult.Yes Then

End_Test(True)

End If

End Sub

'Если в текстовом поле нажимается клавиша Enter, то считывается ответ

Private Sub TextBox1_KeyPress(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyPressEventArgs) Handles TextBox1.KeyPress

If Chr(13) = e.KeyChar Then

Button2_Click(Button2, e)

e.Handled = True

End If

End Sub

End Class