Код программы «Клавиатурный тренажер»
unit Unit9;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, System.IOUtils, Unit10, Unit11, Math,
Vcl.Menus;
type
TForm9 = class(TForm)
GroupBox1: TGroupBox;
ListBox1: TListBox;
Button1: TButton;
Label1: TLabel;
CheckBox1: TCheckBox;
Edit1: TEdit;
Label2: TLabel;
Button2: TButton;
Button3: TButton;
Button4: TButton;
GroupBox2: TGroupBox;
Label3: TLabel;
Edit2: TEdit;
Button5: TButton;
MainMenu1: TMainMenu;
N1: TMenuItem;
procedure FormCreate(Sender: TObject);
procedure RefreshData();
procedure Button3Click(Sender: TObject);
procedure ListBox1Click(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
procedure FormShow(Sender: TObject);
procedure Button4Click(Sender: TObject);
procedure Button5Click(Sender: TObject);
procedure N1Click(Sender: TObject);
private
var findIndex: integer;
var findItemName: String;
{ Private declarations }
public
{ Public declarations }
end;
var
Form9: TForm9;
Implementation
{$R *.dfm}
procedure TForm9.RefreshData();
begin
ListBox1.Clear(); //Очистка листа с группами слов
var wordGroups:= TDirectory.GetFiles('Группы слов'); //Получение файлов из директории
for var i:= 0 to Length(wordGroups) -1 do begin //Проход по каждому файлу
ListBox1.Items.Add(wordGroups[i].Replace('Группы слов\', '')); //Убираем приставку 'Группы слов\' и добавляем в лист групп
end;
Button1.Enabled:= false; //Отключает кнопку редактирования группы
Button3.Enabled:= false; //Отключает кнопку удаление выбранной группы
end;
procedure TForm9.Button1Click(Sender: TObject);
begin
var groupName:= ListBox1.Items[ListBox1.ItemIndex]; //Получение выбранной группы
Form9.Hide(); //Скрытие главной формы
Form10.RichEdit1.Clear(); //Очистка данных группы в другой форме
Form10.Edit1.Text:= groupName; //Изменеине поля с наименование группы в другой форме
Form10.RichEdit1.Lines.LoadFromFile('Группы слов\' + groupName, TEncoding.UTF8); //Загружаем слова в поле другой формы
Form10.groupName:= groupName; //Задаем переменную имени группы в другой форме
Form10.Caption:= 'Изменение группы "' + groupName + '"'; //Задаем название другой форме
Form10.Button1.Caption:= 'Подтвердить изменение группы'; //Изменяем заголовок кнопки
Form10.Button2.Caption:= 'Отменить изменения группы'; //Изменяем заголовок кнопки
Form10.mainForm:= Form9; //Передаем главную форму на другую форму
Form10.Show(); //Показываем форму редактирования формы
end;
procedure TForm9.Button2Click(Sender: TObject);
begin
if(ListBox1.ItemIndex > -1) or ((CheckBox1.Checked) and (ListBox1.Items.Count > 0)) then begin //Если выбрана группы или выбирается случайная группа и количество групп слов > 0
// Начало тестирования
if(CheckBox1.Checked) then begin //Если выбирается случайно
var randomedGroupIndex:= Math.RandomRange(0, ListBox1.Items.Count-1); //Получаем случайный индекс группы
Form11.GroupName:= ListBox1.Items[randomedGroupIndex]; //Задаем группы
end else
Form11.groupName:= ListBox1.Items[ListBox1.ItemIndex]; //Задаем название группы для тестирования
Form11.Show(); //Открываем форму тестирования
Form11.mainForm:= Form9; //Передаем другой форме данную форму
Form11.wordsCountToResolve:= integer.Parse(Edit1.Text); //Задаем количество слов к решению
Form9.Hide(); //Скрываем текущую форму
end else begin
if(ListBox1.Items.Count = 0) then begin //Если нет групп слов
MessageBox(0, 'У вас нет ни единой группы слов. Добавьте группу слов чтобы начать тестирование!', 'Ошибка',0); //Вывод ошибок
exit; //Выход из кода
end;
MessageBox(0, 'Вы не выбрали группу слов для тестирования. Выберите группу слов или поставьте галочку для случайного выбора группы слов и попробуйте снова!', 'Ошибка', 0); //Вывод ошибки
end;
end;
procedure TForm9.Button3Click(Sender: TObject);
begin
var groupName:= ListBox1.Items[ListBox1.ItemIndex]; //Получаем название группы
var msg: String; //Создаем переменную в которой будет хранится сообщеине
msg:= 'Вы действительно хотите удалить группу "' + groupName + '"'; //Задаем сообщение
if(MessageBox(0, PWideChar(msg), 'Подтверждение удаления группы', mb_YesNo) = IDYES) then begin //Диалог. Если выбрано подтверждение
TFile.Delete('Группы слов\' + ListBox1.Items[ListBox1.ItemIndex]); //Удаляет файл с выбранной группой слов
RefreshData(); //Обновляет данные
MessageBox(0, 'Группа успешно удалена!', '', 0); //Вывод сообщения
end;
end;
procedure TForm9.Button4Click(Sender: TObject);
begin
Form9.Hide(); //Скрывает текущую форму
Form10.RichEdit1.Clear(); //Очищает данные в другой форме
Form10.groupName:= ''; //Очищает данные названия группу в другой форме
Form10.Edit1.Text:= ''; //Очищает поле с називанием группы в другой форме
Form10.Caption:= 'Добавление новой группы'; //Изменяет заголовок другой формы
Form10.Button1.Caption:= 'Подтвердить добавление группы'; //Изменяет заголовок кнопки в другой форме
Form10.Button2.Caption:= 'Отменить добавление группы'; //Изменяет заголовок кнопки в другой форме
Form10.mainForm:= Form9; //Передает другой форме данную форму
Form10.Show(); //Показывает форму редактирования/добавления группы
end;
procedure TForm9.Button5Click(Sender: TObject);
begin
if(Edit2.Text = '') then begin //Если наименование искомой группы слов пустое
MessageBox(0, 'Поле с искомым наименованием группы не заполнено! Заполните часть наименования группы и попробуйте снова.', 'Ошибка!', 0); //вывод сообщения
end else begin //иначе
if not (Edit2.Text = findItemName) then begin //Если искомая группа слов не совпадает с той которая в поле
findIndex:= 0; //Переходим в начало
findItemName:= Edit2.Text; //Изменяем наименование искомой группы слов
end;
var itemFinded:= false; //Переменная с информацией о том, найдена ла группа
for var i:= findIndex to ListBox1.Items.Count - 1 do begin //Проход по группам слов в списке
if(ListBox1.Items[i].Contains(Edit2.Text)) then //Если есть совпадение
begin
ListBox1.ItemIndex:= i; //В списке выделяется группа
findIndex:= i + 1; //Переходим на следующую группу
itemFinded:= true; //Даем знать, что группа найдена
break; //Прекращаем искать
end;
end;
if(itemFinded = false) and (findIndex = 0) then //Если не найдено ни ОДНОГО совпадения
MessageBox(0, 'К сожалению программа не смогла найти похожих по наименованию группу', 'Ошибка поиска', 0); //вывод ошибки
if(itemFinded = false) and (findIndex > 0) then begin //Если было найдено хоть одно слово
findIndex:= 0; //Переход в начало
findItemName:= ''; //Задаем искомое имя пустым.
MessageBox(0, 'Совпадений больше не найдено. При следующем поиске программа начнет поиск с начала.', 'Конец поиска', 0); //Вывод информации
end;
end;
end;
procedure TForm9.FormCreate(Sender: TObject);
begin
if not (TDirectory.Exists('Группы слов')) then begin //Если папки с группами слов не существует
TDirectory.CreateDirectory('Группы слов'); //Создание папки
end;
RefreshData(); //Обновление данных
end;
procedure TForm9.FormShow(Sender: TObject);
begin
RefreshData(); //Обновление данных
end;
procedure TForm9.ListBox1Click(Sender: TObject);
begin
var anySelected:= ListBox1.ItemIndex >= 0; //Если любая группа слов выбрана
Button1.Enabled:= anySelected; //Включает кнопку редактирования в зависимости от того, выбрана ли группа
Button3.Enabled:= anySelected; //Включает кнопку удаления в зависимости от того, выбрана ли группа
end;
procedure TForm9.N1Click(Sender: TObject);
begin
MessageBox(0, 'Эта программма позволяет обучиться быстрой печати текста на клавиатуре.', 'Информация', 0); //Вывод информации о программе в меню
end;
unit Unit10;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, System.IOUtils;
type
TForm10 = class(TForm)
RichEdit1: TRichEdit;
Label1: TLabel;
Edit1: TEdit;
Label2: TLabel;
Button1: TButton;
Button2: TButton;
procedure FormClose(Sender: TObject; var Action: TCloseAction);
procedure Button2Click(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
var mainForm: TForm;
var groupName: String;
{ Public declarations }
end;
var
Form10: TForm10;
Implementation
{$R *.dfm}
procedure TForm10.Button1Click(Sender: TObject);
begin
if(RichEdit1.Text = '') then begin //Если поле со словами группы пустое
MessageBox(0, 'В группе слов должно быть как минимум одно слово. Добавьте слова и попробуйте опять.', 'Ошибка!', 0); //Вывод ошибки
exit; //Выход из кода
end;
if(Edit1.Text = '') then begin //Если поле с наименованием группы пустое
MessageBox(0, 'Наименование группы не может быть пустым. Заполните наименование и попробуйте опять.', 'Ошибка!', 0); //Вывод ошибки
exit; //Выход из кода
end;
if(Form10.Caption = 'Добавление новой группы') then begin //Если название формы 'Добавление новой группы'
var wordGroups:= TDirectory.GetFiles('Группы слов'); //Получаем название файлов из папки 'Группы слов'
for var i:= 0 to Length(wordGroups) -1 do begin //Проходимся по каждому файлу
if(wordGroups[i].Replace('Группы слов\', '') = Edit1.Text) then begin //Убираем приставку 'Группы слов\' и проверяем соответствует ли это название какой либо найденной группе
MessageBox(0, 'Группа слов с таким названием уже существует! Выберите другое название или измените существующую группу!', 'Ошибка', 0); //Вывод ошибки
exit; //Выйти из кода
end;
end;
TFile.WriteAllLines('Группы слов\' + Edit1.Text, RichEdit1.Lines.ToStringArray(), TEncoding.UTF8); //В группу слов вписываются данные из поля со словами
end else begin //Если название формы другое (значит редактирование)
if not (Edit1.Text = groupName) then //Если Наименование изменилось
RenameFile('Группы слов\' + groupName, 'Группы слов\' + Edit1.Text); //Переименовываем файл группы слов
TFile.WriteAllLines('Группы слов\' + Edit1.Text, RichEdit1.Lines.ToStringArray(), TEncoding.UTF8); //Вписываем данные в переименованный файл
end;
Form10.Close();
end;
procedure TForm10.Button2Click(Sender: TObject);
begin
if(MessageBox(0, 'Вы действительно хотите вернуться на главную, не сохраняя данных?', 'Подтверждение', mb_YesNo) = IDYES) then //Диалог. При подветрждении закрывает форму
Form10.Close(); //Закрытие формы
end;
procedure TForm10.FormClose(Sender: TObject; var Action: TCloseAction);
begin
mainForm.Show(); //Показ главной формы
end;
end.
unit Unit11;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ExtCtrls, System.IOUtils, Unit12;
type
TForm11 = class(TForm)
Label1: TLabel;
Timer1: TTimer;
Shape1: TShape;
Label3: TLabel;
Label2: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Label9: TLabel;
procedure FormShow(Sender: TObject);
procedure FormKeyPress(Sender: TObject; var Key: Char);
procedure Timer1Timer(Sender: TObject);
procedure FormClose(Sender: TObject; var Action: TCloseAction);
private
errorsCount: integer;
wordsInGroup: TStrings;
currentWordChars: String;
currentWordCharIndex: integer;
currentWord: String;
msGone: integer;
currentWordIndex: integer;
wordsCountSolved: integer;
charsCountSolved: integer;
function GetNextWord(): String;
procedure DoUpdate();
{ Private declarations }
public
groupName: String;
wordsCountToResolve: integer;
mainForm: TForm;
{ Public declarations }
end;
var
Form11: TForm11;
implementation
{$R *.dfm}
function GetWidthText(const Text:String; Font:TFont): Integer;
var
LBmp: TBitmap;
begin
LBmp:= TBitmap.Create; //Создает пустой экземпляр TBitmap
try
LBmp.Canvas.Font:= Font; //Задает шрифт
Result:= LBmp.Canvas.TextWidth(Text); //Получает размер текста
finally
LBmp.Free; //Освобождение памяти
end;
end;
function TForm11.GetNextWord(): String;
label retru;
begin
retru:
if(wordsInGroup.Count > currentWordIndex+1) then begin //Если не достигнут конец слов
if(GetWidthText(wordsInGroup[currentWordIndex+1], Label1.Font) > 525) then begin //Если размер слова превышает 525px
currentWordIndex:= currentWordIndex + 1; //Переход к следующему слову
goto retru; //повтор
end;
Result:= wordsInGroup[currentWordIndex+1]; //Получение следущего слова
currentWordIndex:= currentWordIndex + 1; //Переход к следующиему слову
exit; //Выход из кода
end;
Result:= ''; //Слова закончились, вернуть пустоту.
end;
procedure TForm11.DoUpdate(); begin
Label3.Visible:= charsCountSolved = 0; //Если тестирование начато, то скрывает подсказку
Label1.Caption:= currentWord; //Отображает текущее слово
Label6.Caption:= errorsCount.ToString(); //Отображает количество ошибок
Label7.Caption:= wordsCountSolved.ToString() + ' из ' + wordsCountToResolve.ToString(); //Отображает количество решенных слов из общего количества
var charsPerMin:= Round(charsCountSolved / ((msGone + 1)/1000) * 60); //Рассчитывается скорость печати
Label8.Caption:= charsPerMin.ToString() + ' симв./мин'; //Отображает скорость печати
var enteredTextWidth:= GetWidthText(currentWordChars, Label1.Font); //Получает размер введенных букв
var textWidth:= GetWidthText(currentWord, Label1.Font); //Получает размер текущего слова
var startX:= Round(Label1.Width/2 - textWidth/2) + enteredTextWidth; //Получает X координату в которую будет поставлен выделяющий квадрат
var currentCharWidth:= GetWidthText(currentWord.ToCharArray()[currentWordCharIndex], Label1.Font); //Получает размер текущего символа
Shape1.Left:= startX - 1; //Перемещает квадрат
Shape1.Width:= currentCharWidth + 2; //Меняет ширину квадрата
end;
procedure TForm11.FormClose(Sender: TObject; var Action: TCloseAction);
begin
if(charsCountSolved > 0) then begin //Если количество решенных символов больше нуля
Timer1.Enabled:= false; //Отключение таймера
Form12.timeSecs:= Round((msGone+1)/1000); //Получение прошедших секунд
Form12.errorsCount:= errorsCount; //Количество ошибок
Form12.symbsPerMin:= Round(charsCountSolved / ((msGone + 1)/1000) * 60); //Символов в минуту
Form12.symbolsCount:= charsCountSolved; //Количество символов
Form12.mainForm:= mainForm; //Задает форме результатов переменную с данными главной формы
Form12.Show(); //Открывает форму результатов
end else begin
mainForm.Show(); //Открывает главную форму
end;
end;
procedure TForm11.FormKeyPress(Sender: TObject; var Key: Char);
begin
if(currentWord.ToCharArray()[currentWordCharIndex] = Key) then begin //Если введенная буква с клавиатуры совпадает с той, которую нужно ввести
Shape1.Brush.Color:= clSilver; //Задает цвет кисти для квадрата
if(charsCountSolved = 0) then //Если количество решенных символов больше нуля
Timer1.Enabled:= true; //Включает таймер
charsCountSolved:= charsCountSolved + 1; //Прибавить 1 к количеству решенных символов
currentWordChars:= currentWordChars + currentWord.ToCharArray()[currentWordCharIndex]; //Введеные символы
currentWordCharIndex:= currentWordCharIndex + 1; //Следующий индекс символа в слове
if(currentWordCharIndex < currentWord.Length) then begin //Если текущий индекс символа меньше количества символов текущего слова
DoUpdate(); //Обновление данных
end else begin //иначе
wordsCountSolved:= wordsCountSolved + 1; //Добавляем +1 к решенным словам
currentWord:= GetNextWord(); //Получаем следующее слово
if(currentWord = '') then begin //Если следующего слова нет
if(wordsCountSolved < wordsCountToResolve) then begin //Если количество решенных слов меньше количества слов которые нужно решить
currentWordIndex:= -1; //Начинаем сначала
currentWordCharIndex:= 0; //задаем индекс символа 0
currentWordChars:= ''; //Начинаем сначала
currentWord:= GetNextWord(); //Получаем следующее слово
DoUpdate(); //Обновление данных
exit; //Выход из кода
end;
Close(); //Закрытие формы
exit; //Завершение тестирования
end else begin
if(wordsCountSolved < wordsCountToResolve) then begin //Если количество решенных слов меньше количества которое нужно решить
currentWordCharIndex:= 0; //Начинаем сначала
currentWordChars:= ''; //Начинаем сначала
DoUpdate(); //Обновление данных
end else begin
Close(); //Закрытие формы
exit; //Завершение тестирования
end;
end;
end;
end else begin //Ессли ввели неверную буквы
if(charsCountSolved > 0) then begin //Если количество введенных символов > 0 (Чтобы при начале тестирование не получить ошибку)
Shape1.Brush.Color:= clRed; //Кисть квадрата красным
errorsCount:= errorsCount + 1; //Добавляем к ошибкам +1
DoUpdate(); //Обновляем данные
//Неверный знак
end;
end;
end;
procedure TForm11.FormShow(Sender: TObject);
begin
Shape1.Brush.Color:= clSilver; //Кисть квадрата серая
Timer1.Enabled:= false; //Выключение таймера
msGone:= 0; //Времени прошло на 0
errorsCount:= 0; //Количество ошибок на 0
wordsCountSolved:= 0; //Количество решенных слов на 0
charsCountSolved:= 0; //Количество решенных символов на 0
currentWordIndex:= -1; //На начало
currentWordCharIndex:= 0; //На начало
currentWordChars:= ''; //На начало
wordsInGroup:= TStringList.Create; //Создание экзмепляра массива слов в группе
wordsInGroup.LoadFromFile('Группы слов\' + groupName, TEncoding.UTF8); //Загрузка слов
currentWord:= GetNextWord(); //Получение следующего слова
DoUpdate(); //Обновление данных
end;
procedure TForm11.Timer1Timer(Sender: TObject);
begin
msGone:= msGone + Timer1.Interval; //Обновляем пройденное время
end;
end.
unit Unit12;
interface
uses
Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls;
type
TForm12 = class(TForm)
Label1: TLabel;
Label2: TLabel;
Label3: TLabel;
Label4: TLabel;
Label5: TLabel;
Label6: TLabel;
Label7: TLabel;
Label8: TLabel;
Button1: TButton;
Label9: TLabel;
Label10: TLabel;
procedure FormShow(Sender: TObject);
procedure Button1Click(Sender: TObject);
private
{ Private declarations }
public
var timeSecs, symbsPerMin, symbolsCount, errorsCount: integer;
mainForm: TForm;
{ Public declarations }
end;
var
Form12: TForm12;
Implementation
{$R *.dfm}
uses Unit9
procedure TForm12.Button1Click(Sender: TObject);
begin
mainForm.Show(); //Показать главную форму
Close(); //Закрыть текущую форму
end;
procedure TForm12.FormShow(Sender: TObject);
begin
var errorsPercent:= errorsCount/symbolsCount*100; //Получение процент ошибок
Label6.Caption:= errorsCount.ToString() + ' (' + errorsPercent.ToString() + '%)'; //Вывод процента количества ошибок
if(errorsPercent < 5) then begin //Если процент ошибок меньше 5
Label8.Caption:= 'ОТЛИЧНО'; //Вывод результата
Label8.Font.Color:= clLime; //Назначение цвета
end else begin
if(errorsPercent < 10) then begin //Если процент ошибок меньше 10
Label8.Caption:= 'ХОРОШО';//Вывод результата
Label8.Font.Color:= clGreen;//Назначение цвета
end else begin
if(errorsPercent < 20) then begin //Если процент ошибок меньше 20
Label8.Caption:= 'УДОВЛЕТВОРИТЕЛЬНО'; //Вывод результата
Label8.Font.Color:= clSkyBlue; //Назначение цвета
end else begin //Если процент ошибок >= 20
Label8.Caption:= 'УДОВЛЕТВОРИТЕЛЬНО'; //Вывод результата
Label8.Font.Color:= clRed; //Назначение цвета
end;
end;
end;
Label10.Caption:= timeSecs.ToString() + ' секунд'; //Вывод количество пройденных секунд тестирования
Label4.Caption:= symbolsCount.ToString(); //Вывод количества решенных символов
Label2.Caption:= symbsPerMin.ToString() + ' симв./мин'; //Вывод количества символов в минуту
end;