Міністерство Освіти і Науки України
Націольний Університет “Львівська політехніка”
Кафедра автоматизованих систем
Курсова робота
З дисципліни
“Системне програмування та операційні системи”
на тему:
“Тестування знань”
Львів-2011 р.
Міністерство Освіти і Науки України
Націольний Університет “Львівська Політехніка”
Кафедра автоматизованих систем
Завдання на курсову роботу
З дисципліни
“ Системне програмування та операційні системи ”
Тестування знань
Спеціальна частина завдання:
Розробити алгоритм вирішення задачі.
Програма повинна мати зручний для користувача інтерфейс.
Провести огляд літератури.
Завдання видано:
Керівник:
Студент:
Зміст
Вступ
1. Огляд літератури .................................................................................................5
2. Постановка та алгоритм вирішення задачі.........................................................9
3. Опис програмного комплексу............................................................................10
4. Інструкція користувачеві програми .................................................................14
Висновки .................................................................................................................16
Список використаної література ...........................................................................17
Додатки....................................................................................................................18
Додаток 1. Текст головної програми
Додаток 2. Тексти підпрограми
Вступ
Програма “тестова система знань ” призначена для швидкої перевірки знань учнів по певному матеріалі, який був пройдений під час навчання. По кількості набраних балів під час тестування можна оцінити рівень знань учня або студента. Даний продукт призначений для використання як у домашніх умовах, так і в робочих, наприклад у школі, де може стояти навіть старенький комп’ютер під управлінням MS DOS.
Дана програма легка у експлуатації, користувачеві, після запуску програми потрібно тільки вводити правильну відповідь. База питань знаходиться у окремому файлі, який можна замінити на інший файл з новими питаннями і, який опрацьовується командами мов програмування Турбо C та Турбо Сі.
1. Огляд літератури
Особливе місце в мові C займають масиви символів.
Рядкова константа, чи рядок, являє собою сукупністьсимволів, укладену в апострофи. Рядок - це елементарна конструкція мови C. Як і числові константи, вони можуть бути описані в розділіопису констант.
Тип String без указівки довжини сполучимо з усіма типами рядків.
У пам'яті ЕОМ рядок займає кількість байтів, на одиницю більшу її довжини. Нульовий байт рядка містить його довжину.
Для рядків визначені операції присвоювання, злиття і порівняння.Порівняннярядків відбувається посимвольно, починаючи з першого символу.
При введенні рядкових змінних кількість символів, що вводяться, може бути менше, ніж довжина рядка. У цьому випадку символи, що вводяться, розміщуются з початку рядка, а байти, що залишилися, заповнюються пробілами. Якщо кількість символів, що вводяться, перевищує довжину рядка, зайві символи відкидаються.
Алгоритм рішення задачі проектується шляхом декомпозиції всієї задачі в окремі підзадачі. Звичайно підзадачі реалізуються у вигляді підпрограм.
У мові C є два типи підпрограм - процедури і функції.
Процедура і функція - це іменована послідовність описіві операторів. При використанні процедур чи функцій C - програма повинна містити текст процедури чи функції і звертання до процедури чи функції. Тексти процедур і функцій містяться в розділописів процедур і функцій.
Процедура може містити такі - же розділи описів, що і C - програма, а саме: розділи опису модулів, міток, констант, типів, перемінних, процедур і функцій.
Запис являє собою сукупність обмеженого числа логічно зв'язаних компонентів, що належать до різних типів. Компоненти запису називаються полями, кожне з який визначається ім'ям. Полеь запису містить ім'я полч, слідом за яким через двокрапку вказуєся тип цього поля. Поля запису можуть відноситися до будь-якого типу, допустимому в мові C, за винятком файлового типу.
Звертання до запису в цілому допускається тільки в операторах присвоєння, де ліворуч і праворуч від знака присвоювання використовуються імена записів однакового типу. В всіх інших випадках оперують окремими полями записів. Щоб звернутися до окремого компонента запису, необхідно задати ім'я запису і через крапку вказати ім'я потрібного поля.
Введення файлового типу в мову C викликано необхідністю забезпечити можливість роботи з периферійними (зовнішніми) пристроями ЕОМ, призначеними для введення, висновку і збереження даних.
Файловий тип даних чи файл визначає упорядковану сукупність довільного числа однотипних компонентів.
Загальна властивість масиву, безлічі і записи полягає в тім, щокількість їхніх компонентів визначено на етапі написання програми, тоді як кількість компонентів файлу в тексті програми не визначаєтьсяі може бути довільним.
При роботі з файлами виконуються операції введення - висновку. Операціявведення означає перепис даних із зовнішнього пристрою (із вхідногофайлу) в основну пам'ять ЕОМ, операція висновку - це пересилання даних з основної пам'яті на зовнішній пристрій (у вихідний файл).
У програмах мовою C імена файлів задаються за допомогою рядків.
З файловою системою C зв'язане поняття буфера введення -висновку. Введення і висновок даних здійснюється через буфер. Буфер - цеобласть у пам'яті, що виділяється для кожного файлу. При записі вфайл вся інформація спочатку направляється в буфер і там накопичується доти, поки весь обсяг буфера не буде заповнений. Тільки після цього чи після спеціальної команди скидання відбувається передача даних на зовнішній пристрій. При читанні з файлу дані спочатку зчитуються у буфер, причому даних зчитується не стільки, скільки запитується,а скільки поміститься в буфер.
Основні типи даних розділяються на три категорії: цілоцисельні, із крапкою, що плаває, і невизначені(voіd). Цілоцисельні типи даних працюють з цілими числами. Типи даних із крапкою, що плаває, працюють з даними ,які мають дробову частину. Невизначений тип даних відповідає порожній множині значень.
У мові С основними типами даних є:
•char - цілочисельний тип, містить символи.
•іnt - є цілочисельним типом, містить цілі цифри.
•short - тип даних short іnt (чи скорочено short) є цілочисельним типом, що містить цілі числа,які по розміру менші чи дорівнюють типу іnt.
•long - тип даних long іnt (чи скорочено long) є цілочисельним типом, що містить цілі числа, які по розміру більші чи рівні типу іnt.
•double - тип даних із крапкою, що плаває.
•float - найменший тип даних із крапкою, що плаває.
•long double - тип даних із крапкою, що плаває і більший за double.
Усяку задачу можна розбити на кілька підзадач. Також і в програмі ми можемо використовувати функції для розбивки її на кілька підпрограм. Виконання програми починається завжди з функції maіn(). Коли в програмі вмтречается ім'я функції відбувається звертання до їй і керування передається їй. Після виконання функції керування передається в те місце відкіля вона була викликана. Формально функція виглядає так:
тип ім'я(список_параметрів)
{ інструкції
}
Отут: тип - тип, що це повертається,(тип того що повертає функція), ім'я - це назва функції і список_параметрів - це параметри які передаються функції. У функціях для повернення результату використовується інструкція return, вона повертає яке або значення в те місце відкіля була викликана функція.
Тип struct позваляє програмісту об'єднати кількатрохи компонент у перемінну з одним ім'ям. Члени структури можуть бути різних типів. Як приклад визначимо структуру квартиру, що описує. Ця структура буде зберігати такі ознаки квартири як площа, число кімнат, номер, прізвище головного квартиронаймача.
struct apartment
{іnt count_rooms;
іnt area;
іnt number;
char fіo[20];};
Оператори порівняння, рівності і логічні. У Смається логічний тип даних bool який може приймати тільки два значення true(істина) чи false(неправда). Цей тип даних використовується для контролю виконання інструкцій різних типів. У наступній таблиці представлені інструкції С, найбільше часто використовувані для керування логікою виконання.
Оператори порівняння, рівності і логічні
Оператори сравненияменьше<більше> чименше дорівнює<= чибільше дорівнює>=Оператори равенстваравно==не дорівнює!=Логічні операторыотрицание!логічне і&&логічне или||
Дуже важливо не плутати оператори рівності і присвоювання, наприклад a==b - це перевірка на рівність тобто якщо a і b рівні те вираження поверне true(істина) у противному випадку false(неправда), а у вираженні a=b перемінна a стане дорівнює b.
Опис функцій роботи з файломи знаходяться в бібліотеці stdіo.h
Спочатку треба створити покажчик на перемінну типу FІLE ( FІLE* fіle; ).
Відкриття файлу виробляється викликом функції fopen ( fіle = fopen( fіle_name, "w" ); )
Перший параметр цієї функції - ім'я файлу, другий - вказує в якому режимі повинний бути відкритий файл. "w" - відкрити для запису, "r" - відкрити для читання, "a" - доповнення файлу( це найбільш використовувані режими, хоча є й інші ). Запис і зчитування даних з файлу здійснюється наступними функціями : fputc, fputs, fgetc, fgets, fprіntf, fscanf( опис цих функцій дивитеся в stdіo.h).
Закриття файлу здійснюється викликом функції fclose ( fclose( fіle ); ).\
2. Постановка та алгоритм вирішення задачі
Інтерфейс тесту.
Формування файлу з питаннями;
Опрацюванням інформації, яка зчитується з файлу.
Перевірка на правильність відповіді, підрахунок балів.
Програма відноситься до класу програм роботи з файлами даних. Основні методи опрацювання записів тесту пов’язані з опрацюванням вхідної інформації, яка зчитується з файлу. Тип файлу даних – текстовий.
Файл з записами представлений такою структурою:
кожний рядок файлу є окремим записом питання;
кожне поле запису є питанням та варіантами відповідей .
Блок схема алгоритму
3. Опис програмного комплексу.
Загальна характеристика програми:
Ім’я програми – КТЕСТ
Назва файлів – КТЕСТ.exe (виконавчий файл),
КТЕСТ.срp (файл з вихідним кодом програми на Turbo С, як додаток),
data (файл даних тесту),
Мова програмування – Turbo C.
Об’єм виконавчого файлу – 499 Кбайт
Призначення програми:
Тестова система знань.
Вхідна інформація:
Вхідна інформація – варіанти відповідей, які вводить з клавіатури користувач.
Вихідна інформація:
Вихідна інформація виводиться на екран у вигляді повідомленя,що сповіщає про кількість балів і оцінку, яку заробив користувач.
4. Інструкція користувачеві програми
Функціональні можливості програми “Тестова система знань”:
1. Запускаємо exe файл.
2. На екрані появляється вікно із списком запитань і варіантами відповіді на них.
3. З переліку варіантів відповіді вибираємо правильний варіант, після чого натискаємо клавішу „Наступне” в даному вікні.
4. Повторюємо пункт 3 доти, доки не відповімо на всі запитання.
5. Потім натискаємо клавішу ”Завершити”, для того щоб отримати результат.Висновки
Виконуючи дану програму я краще оволодів технікою програмування на Turbo C.
Основний результат виконання програми – це зручність швидкої перевірки знань учнів та студентів.
Література
Прата С. Програмування на С. Москва-Київ: Diasoft, 2000
Зубов В.С. Программирование на языке Турбо C 6.0, 7.0
Шилдт Г. Программирование на С и С++ .
Фаронов В.В. Турбо C 7.0. Учебное пособие. - М.: Нолидж, 1997.
Фаронов В.В. Турбо C 7.0. Практика програмирования. Учебное пособие. - М.: Нолидж, 1997.
ДОДАТОК 1
Текст головної програми:
//---------------------------------------------------------------------------
#include <vcl.h>
#pragma hdrstop
USERES("KTest.res");
USEFORM("Unit1.cpp", Form1);
//---------------------------------------------------------------------------
WINAPI WinMain(HINSTANCE, HINSTANCE, LPSTR, int)
{
try
{
Application->Initialize();
Application->CreateForm(__classid(TForm1), &Form1);
Application->Run();
}
catch (Exception &exception)
{
Application->ShowException(&exception);
}
return 0;
}
//---------------------------------------------------------------------------
Додаток 2
Текст підпрограми
#include <vcl.h>
#pragma hdrstop
#include "Unit1.h"
#include <algorithm>
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma link "CGRID"
#pragma resource "*.dfm"
TForm1 *Form1;
#include <vector.h>
// Структура задає питання
typedef struct _Question {
AnsiString Question; // питання
TStringList *Answers; // список варіантів відповідей
vector <int> RightAnswers; // список правильних відповідей
vector <int> SelectAnswers; // список вибраних відповідей
} Question;
// Базовий клас "Питання"
class CustomQuestions {
public:
AnsiString Subject; // тема
vector <Question> Questions; // список питань
int LoadFromFile(AnsiString); // Функція завантаження списку питань із файлу
virtual ~CustomQuestions();
};
CustomQuestions::~CustomQuestions()
{
Questions.clear();
}
// Функція завантаження списку питань із файлу
// Використовується клас TIniFile для зчитування питань із файлу
// (Використовується стандартний текстовий формат Windows INI файлів)
// Підтримується наступний формат вхідного файлу:
// [Main]
// Subject=Назва предмету
// Questions=n (n - к-ть запитань)
// [Q1]
// Question=Запитання
// 1=Варіант відповіді №1
// 2=Варіант відповіді №2
// ...
// m=Варіант відповіді №m
// Answers=1,2,3 (номери правильних відповідей)
// Секцій [Qi] повинно бути n штук
int CustomQuestions::LoadFromFile(AnsiString FileName)
{
TIniFile *pif = new TIniFile(FileName);
int i, j, CountOfQuestions;
AnsiString s, Answer;
char *str, *p;
Questions.clear();
Subject = pif->ReadString("Main", "Subject", "");
CountOfQuestions = pif->ReadInteger("Main", "Questions", 0);
for (i=0; i<CountOfQuestions; i++)
{
Question Q;
s = "Q" + IntToStr(i+1);
Q.Question = pif->ReadString(s, "Question", "");
Q.Answers = new TStringList();
j = 0;
while (true)
{
Answer = pif->ReadString(s, IntToStr(++j), "");
if (Answer == "") break;
Q.Answers->Add(Answer);
}
Q.SelectAnswers = vector <int> (Q.Answers->Count, 0);
Answer = pif->ReadString(s, "Answers", "");
str = (char *)malloc(Answer.Length()+1);
strcpy(str, Answer.c_str());
p = strtok(str, ",");
while (p)
{
j = StrToInt(p);
Q.RightAnswers.push_back(j-1);
p = strtok(NULL, ",");
}
free(str);
Questions.push_back(Q);
}
delete pif;
return 0;
}
// Дочірній клас, породжений від батьківського CustomQuestions
// Даний клас дозволяэ не лише зчитувати ы зберыгати запитання, а
// ще й відображати їх на екрані
class Questions : public CustomQuestions {
void __fastcall LabelClick(TObject *);
int CurrQuestion;
public:
int Enabled;
TScrollBox *ScrollBox;
TLabel *NumberLabel;
TLabel *QuestionLabel;
vector <TLabel *> AnswerLabels;
vector <TCheckBox *> AnswerCheckBoxes;
int ShowQuestion(int);
Questions(Classes::TComponent *);
~Questions();
};
// Конструктор класу Questions
// Ініціалызація внутрішніх змінних
Questions::Questions(Classes::TComponent *AOwner)
{
Enabled = true;
ScrollBox = new TScrollBox(AOwner);
ScrollBox->Parent = (TWinControl *)AOwner;
ScrollBox->Align = alClient;
ScrollBox->BorderStyle = bsNone;
ScrollBox->VertScrollBar->Tracking = true;
ScrollBox->HorzScrollBar->Tracking = true;
ScrollBox->Font->Name = "Times New Roman";
NumberLabel = new TLabel(ScrollBox);
NumberLabel->Parent = (TWinControl *)ScrollBox;
NumberLabel->Top = 8;
NumberLabel->Left = 8;
NumberLabel->Font->Name = "Comic Sans MS";
NumberLabel->Font->Size = 18;
NumberLabel->Font->Style = NumberLabel->Font->Style << fsUnderline;
QuestionLabel = new TLabel(ScrollBox);
QuestionLabel->Parent = (TWinControl *)ScrollBox;
QuestionLabel->Top = NumberLabel->Top + NumberLabel->Height + 8;
QuestionLabel->Left = 8;
QuestionLabel->WordWrap = true;
QuestionLabel->Width = ScrollBox->ClientWidth - 16;
QuestionLabel->Font->Color = clBlue;
QuestionLabel->Font->Size = 18;
}
// Деструктор класу Questions
Questions::~Questions()
{
vector <TLabel*>::iterator ali;
vector <TCheckBox*>::iterator acbi;
for (ali=AnswerLabels.begin(); ali!=AnswerLabels.end(); ali++) delete *ali;
for (acbi=AnswerCheckBoxes.begin(); acbi!=AnswerCheckBoxes.end(); acbi++) delete *acbi;
AnswerLabels.clear();
AnswerCheckBoxes.clear();
}
// Відображає питання на екрані
int Questions::ShowQuestion(int n)
{
int i, j, m;
TLabel *Label;
TCheckBox *CheckBox;
if (n<0) n = Questions.size() - 1;
if (n>Questions.size() - 1) n = 0;
CurrQuestion = n;
NumberLabel->Enabled = Enabled;
QuestionLabel->Enabled = Enabled;
int Top = NumberLabel->Top + NumberLabel->Height + 8;
NumberLabel->Caption = "Питання №" + IntToStr(n+1);
QuestionLabel->Top = Top;
QuestionLabel->WordWrap = True;
QuestionLabel->Width = ScrollBox->ClientWidth - 16;
QuestionLabel->Caption = Questions[n].Question;
Top+= QuestionLabel->Height + 8;
vector<TLabel*>::iterator ali;
vector<TCheckBox*>::iterator acbi;
for (ali=AnswerLabels.begin(); ali!=AnswerLabels.end(); ali++) delete *ali;
for (acbi=AnswerCheckBoxes.begin(); acbi!=AnswerCheckBoxes.end(); acbi++) delete *acbi;
AnswerLabels.clear();
AnswerCheckBoxes.clear();
for (i=0; i<Questions[n].Answers->Count; i++)
{
Label = new TLabel(ScrollBox);
Label->Parent = ScrollBox;
Label->Left = 48;
Label->Top = Top;
Label->WordWrap = True;
Label->Font->Name = "Courier New";
Label->Font->Size = 18;
Label->Width = ScrollBox->ClientWidth - Label->Left - 8;
Label->Caption = IntToStr(i+1) + ") " + Questions[n].Answers->Strings[i];
Label->OnClick = LabelClick;
Label->Tag = i;
Label->Enabled = Enabled;
AnswerLabels.push_back(Label);
CheckBox = new TCheckBox(ScrollBox);
CheckBox->Parent = ScrollBox;
CheckBox->Left = Label->Left - CheckBox->Height - 8;
CheckBox->Top = Top + (Label->Height - CheckBox->Height)/2;
CheckBox->Width = CheckBox->Height;
CheckBox->Checked = Questions[n].SelectAnswers[i];
CheckBox->OnClick = LabelClick;
CheckBox->Tag = i;
CheckBox->Enabled = Enabled;
AnswerCheckBoxes.push_back(CheckBox);
Top+= Label->Height + 8;
}
return n;
}
// Обробник події OnClick для компонент TLabel і TCheckBox
void __fastcall Questions::LabelClick(TObject *Sender)
{
int i = ((TComponent *)Sender)->Tag;
AnsiString ClassName = Sender->ClassName();
if (i < AnswerCheckBoxes.size())
{
if (ClassName == "TLabel")
{
AnswerCheckBoxes[i]->OnClick = NULL;
AnswerCheckBoxes[i]->Checked = !AnswerCheckBoxes[i]->Checked;
AnswerCheckBoxes[i]->OnClick = LabelClick;
}
Questions[CurrQuestion].SelectAnswers[i] = AnswerCheckBoxes[i]->Checked;
}
}
Questions *Q;
int CurrQuestion;
TDateTime deadtime;
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner) : TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button2Click(TObject *Sender)
{
CurrQuestion = Q->ShowQuestion(CurrQuestion-1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button3Click(TObject *Sender)
{
CurrQuestion = Q->ShowQuestion(CurrQuestion+1);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormCreate(TObject *Sender)
{
int i, j;
AnsiString CurrentDir = GetCurrentDir();
i = CurrentDir.Length();
if (CurrentDir[i] != '\\') CurrentDir+= "\\";
Q = new Questions(Panel2);
Q->LoadFromFile(CurrentDir + "data.ask");
Q->ShowQuestion(0);
Panel1->Caption = Q->Subject;
Label1->Caption = "Всього питань: " + IntToStr(Q->Questions.size());
ListBox1->Clear();
for (i=0; i<Q->Questions.size(); i++)
{
ListBox1->Items->Add(Q->Questions[i].Question);
}
deadtime = Time()+ TDateTime(0, 30, 0, 0);
FormResize(Sender);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button4Click(TObject *Sender)
{
GroupBox2->Visible = !GroupBox2->Visible;
if (GroupBox2->Visible)
Splitter1->Align = alRight;
else
Splitter1->Align = alNone;
}
//---------------------------------------------------------------------------
void __fastcall TForm1::ListBox1Click(TObject *Sender)
{
CurrQuestion = Q->ShowQuestion(ListBox1->ItemIndex);
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Timer1Timer(TObject *Sender)
{
TDateTime x = deadtime - Time();
if (x <= TDateTime(0,0,0,0))
{
Button5Click(Sender);
Timer1->Enabled = false;
}
Label2->Caption = "Залишилось часу: " + x.TimeString();
}
//---------------------------------------------------------------------------
#define MAX_CODE 32
char code[MAX_CODE+1];
char *codelist[] = {
"timebonus",
"ineedsomehelp",
"helpme"
};
void __fastcall TForm1::FormKeyPress(TObject *Sender, char &Key)
{
int i, j, k;
vector <Question>::iterator itq;
vector <int>::iterator it;
MoveMemory(code, code+1, MAX_CODE);
code[MAX_CODE-1] = Key;
for (i=0; i<sizeof(codelist)/sizeof(*codelist); i++)
for (j=0; j<MAX_CODE; j++)
if (!strcmp(codelist[i], code+j))
{
switch (i)
{
case 0:
deadtime+= TDateTime(0, 5, 0, 0);
break;
case 1:
for (itq=Q->Questions.begin(); itq!=Q->Questions.end(); itq++)
{
for (it=itq->SelectAnswers.begin(); it!=itq->SelectAnswers.end(); it++)
*it = 0;
for (it=itq->RightAnswers.begin(); it!=itq->RightAnswers.end(); it++)
itq->SelectAnswers[*it] = 1;
}
Q->ShowQuestion(CurrQuestion);
break;
case 2:
itq = &Q->Questions[CurrQuestion];
for (it=itq->SelectAnswers.begin(); it!=itq->SelectAnswers.end(); it++)
*it = 0;
for (it=itq->RightAnswers.begin(); it!=itq->RightAnswers.end(); it++)
itq->SelectAnswers[*it] = 1;
Q->ShowQuestion(CurrQuestion);
break;
}
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button5Click(TObject *Sender)
{
int i, count=0, Count=0;
vector <Question>::iterator itq;
vector <int>::iterator it;
Timer1->Enabled = false;
Button5->OnClick = NULL;
Button5->Enabled = false;
Q->Enabled = false;
Q->ShowQuestion(CurrQuestion=0);
for (itq=Q->Questions.begin(); itq!=Q->Questions.end(); itq++)
{
Count+= itq->RightAnswers.size();
for (it=itq->SelectAnswers.begin(), i=0; it!=itq->SelectAnswers.end(); it++, i++)
if (*it)
{
if (find(itq->RightAnswers.begin(), itq->RightAnswers.end(), i)!= itq->RightAnswers.end())
count++;
else
count--;
}
}
Panel4->Caption = FloatToStr(100.0*count/Count) + "%";
GroupBox3->BringToFront();
GroupBox3->Visible = true;
}
//---------------------------------------------------------------------------
// Обробник натискання клавіш в програмі
// Дозволяє з клавіатури відмічати питання з номерами від 1 до 9
void __fastcall TForm1::FormKeyDown(TObject *Sender, WORD &Key, TShiftState Shift)
{
int i;
if (Key >= '1' && Key<='9')
{
i = Key - '1';
if (i < Q->AnswerCheckBoxes.size())
Q->AnswerCheckBoxes[i]->Checked = !Q->AnswerCheckBoxes[i]->Checked;
}
}
//---------------------------------------------------------------------------
void __fastcall TForm1::FormResize(TObject *Sender)
{
GroupBox3->Left = (ClientWidth - GroupBox3->Width)/2;
GroupBox3->Top = (ClientHeight - GroupBox3->Height)/2;
}