Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ЛАБ_ПОА_2012.doc
Скачиваний:
2
Добавлен:
03.05.2019
Размер:
8.49 Mб
Скачать

Проектирование приложения. Выбор, размещение и задание свойств компонентов. Коды классов, функций и обработчиков событий.

Сохраните модуль под именем LR_5, а проект – под именем PR_LR_5.

Достаточно полное представление об интерфейсе можно получить из рис.5.1, рис.5.2 и заголовочного файла LR_5.h (см. ниже). Отметим лишь, чо для компонентов Label1,..,8 и Edit1,..,8 установлен шрифт Font = жирный, размер 10, а сконструированное меню представлено на рис.5.3.

Все функции – для работы со стеком и записями арифметических выражений, а также данные для функций поместим в класс Stack, содержание которого представлено на рис.5.3.

Для размещения класса в проекте использован модуль, не связанный с формой. Чтобы создать такой модуль, нужно выполнить команду Файл/Новый/Другое… и открывшемся окне Новые элементы на странице Новый щелкнуть на пиктограмме Модуль. Модулю дано имя f_5. В заголовочном файле этого модуля f_5.h находятся объявления структурных типов для стеков и класса, а в файле реализации модуля f_5.cpp – реализация класса (определения функций-элементов класса).

Рис.5.1 – форма по окончании проектирования

Рис.5.2 - видна структура меню Рис.5.3 - структурные типы и классы

проекта

Заголовочный файл LR_5.h модуля LR_5.

//---------------------------------------------------------------------------

#ifndef LR_5H

#define LR_5H

//---------------------------------------------------------------------------

#include <Classes.hpp>

#include <Controls.hpp>

#include <StdCtrls.hpp>

#include <Forms.hpp>

#include <Menus.hpp>

#include <ActnList.hpp>

#include <ImgList.hpp>

#include <ComCtrls.hpp>

#include <ToolWin.hpp>

//---------------------------------------------------------------------------

class TForm1 : public TForm

{

__published: // IDE-managed Components

TLabel *Label1;

TLabel *Label2;

TEdit *Edit1;

TEdit *Edit2;

TLabel *Label3;

TEdit *Edit3;

TLabel *Label4;

TEdit *Edit4;

TLabel *Label5;

TEdit *Edit5;

TLabel *Label6;

TEdit *Edit6;

TLabel *Label7;

TEdit *Edit7;

TLabel *Label8;

TEdit *Edit8;

TActionList *ActionList1;

TImageList *ImageList1;

TAction *ANew;

TAction *AMod;

TAction *ARun;

TAction *AExit;

TMainMenu *MainMenu1;

TMenuItem *N1;

TMenuItem *N2;

TMenuItem *N3;

TMenuItem *N4;

TMenuItem *N5;

TMenuItem *N6;

TToolBar *ToolBar1;

TToolButton *ToolButton1;

TToolButton *ToolButton2;

TToolButton *ToolButton3;

TToolButton *ToolButton4;

void __fastcall FormCreate(TObject *Sender);

void __fastcall N2Click(TObject *Sender);

void __fastcall N3Click(TObject *Sender);

void __fastcall N4Click(TObject *Sender);

void __fastcall N6Click(TObject *Sender);

private: // User declarations

public: // User declarations

__fastcall TForm1(TComponent* Owner);

};

//---------------------------------------------------------------------------

extern PACKAGE TForm1 *Form1;

//---------------------------------------------------------------------------

#endif

Заголовочный файл f_5.h модуля f_5.

//---------------------------------------------------------------------------

#ifndef f_5H

#define f_5H

//---------------------------------------------------------------------------

//структура для элемента стека операций

struct Node_op

{

char c;

Node_op* p;

};

//---------------------------------------------------------------------------

//структура для элемента стека чисел

struct Node_num

{

float c;

Node_num* p;

};

//---------------------------------------------------------------------------

//перечисление для контроля ошибок при вводе

typedef enum {all_true=1, bad_operands, few_brackets, much_brackets,

few_operands, few_operators}errors;

//---------------------------------------------------------------------------

class Stack

{

public:

char* s; //исходная строка

char* sv; //вспомогательная строка

Node_op* t1; //указатель на вершину стека операций

Node_num* t2; //указатель на вершину стека чисел

void Stack_init(); //задание параметров объекта класса

void check(); //проверка корректности введенного выражения

void revers_before(); //реверсирование входной строки

void revers_after(); //реверсирование постфиксной записи

void bspaces(); //расстановка пробелов в строке

void postfix(); //преобразование в постфиксную запись

float calc(); //вычисление выражения в постфиксной записи

void out_err_code(); //вывод сообщения

errors err_code; //код ошибки

~Stack(); //деструктор класса

private:

int prioritet_stack();//определение приоритета оператора на вершине стека

bool operand_true(char c); //проверка корректности операнда

void first1(char c); //создание стека операций

void push1(char c); //добавление в стек операций

char pop1(); //выталкивание из стека операций

void first2(float c); //создание стека чисел

void push2(float c); //добавление в стек чисел

float pop2(); //выталкивание из стека чисел

};

#endif

Файл реализации f_5.cpp модуля f_5.

//---------------------------------------------------------------------------

#pragma hdrstop

#include "f_5.h"

#include "string.h"

#include "stdlib.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

void Stack::Stack_init()

{

t1=0;

t2=0;

s=new char[100];

sv=new char[100];

err_code=all_true;

}

//-------------------------------------------------------------------------

Stack::~Stack()

{

delete[] s;

delete[] sv;

}

//---------------------------------------------------------------------------

void Stack::first1(char c)

{

Node_op* pv=new Node_op;

pv->c=c;

pv->p=0;

t1=pv;

}

//---------------------------------------------------------------------------

void Stack::push1(char c)

{

Node_op* pv=new Node_op;

pv->c=c;

pv->p=t1;

t1=pv;

}

//--------------------------------------------------------------------------

char Stack::pop1()

{

char z=t1->c;

Node_op* pv=t1;

t1=t1->p;

delete pv;

return z;

}

//--------------------------------------------------------------------------

void Stack::first2(float c)

{

Node_num* pv=new Node_num;

pv->c=c;

pv->p=0;

t2=pv;

}

//---------------------------------------------------------------------------

void Stack::push2(float c)

{

Node_num* pv=new Node_num;

pv->c=c;

pv->p=t2;

t2=pv;

}

//--------------------------------------------------------------------------

float Stack::pop2()

{

float z=t2->c;

Node_num* pv=t2;

t2=t2->p;

delete pv;

return z;

}

//--------------------------------------------------------------------------

bool Stack:: operand_true(char c)

{

if(c>='0'&&c<='9'||c>='A'&&c<='Z'||

c>='a'&&c<='z'||c=='.') return true;

else return false;

}

//---------------------------------------------------------------------------

int Stack::prioritet_stack()

{

if(t1->c=='(')return 3;

if(t1->c=='+'||t1->c=='-')return 1;

return 2;

}

//---------------------------------------------------------------------------

void Stack::check()

{

int sk=0;

int rang=0;

int l=strlen(s);

int i=0;

if(s[0]==')')

{err_code=much_brackets; return;}

if(s[0]=='*'||s[0]=='/')

{err_code=few_operands; return;}

for(i; i<l; i++)

{

if(s[i]=='(')

{

if(i>0&&operand_true(s[i-1]))

{err_code=few_operators; return;}

if(s[i+1]=='*'||s[i+1]=='/'||s[i+1]==')')

{err_code=few_operands; return;}

sk++; continue;

}

if(s[i]==')')

{ if((i>0)&&(s[i-1]=='*'||s[i-1]=='+'||s[i-1]=='-'||s[i-1]=='/'))

{err_code=few_operands; return;}

if(operand_true(s[i+1])||s[i+1]=='(')

{err_code=few_operators; return;}

sk--; continue;

}

if(s[i]=='*'||s[i]=='/'||s[i]=='+'||s[i]=='-')

{rang++; continue;}

if(operand_true(s[i]))

{

while (operand_true(s[++i]));

i--;

rang--;

}

else

{

err_code=bad_operands;

return;

}

}

s[i]='\0';

if(rang>-1) {err_code=few_operands; return;}

if(rang<-1) {err_code=few_operators; return;}

if(sk>0) {err_code=few_brackets; return;}

if(sk<0) {err_code=much_brackets; return;}

}

//--------------------------------------------------------------------------

void Stack::revers_before()

{

int i=strlen(s)-1;

int j=0;

for(i;i>=0;i--)

{

if(s[i]=='(') sv[j++]=')';

else if(s[i]==')')sv[j++]='(';

else sv[j++]=s[i];

}

sv[j]='\0';

strcpy(s,sv);

//а теперь реверсируем операнды

int k;

for (i=0;i<strlen(s);i++)

{

if(operand_true(s[i]))

{

k=1;

while (operand_true(s[++i]))k++;

i--;

for(j=0;j<k;j++)

{s[i+1-k+j]=sv[i-j];}

}

}

}

//--------------------------------------------------------------------------

void Stack::revers_after()

{

int i=0;

int j=strlen(s)-1;

for(j;j>=0;j--) sv[i++]=s[j];

sv[i]='\0';

strcpy(s,sv);

//а теперь реверсируем операнды

int k;

for (i=0;i<strlen(s);i++)

{

if(operand_true(s[i]))

{

k=1;

while (operand_true(s[++i]))k++;

i--;

for(j=0;j<k;j++)

{s[i+1-k+j]=sv[i-j];}

}

}

}

//-------------------------------------------------------------------------

void Stack::bspaces()

{

int l=strlen(s);

int i=0,j=0;

for(i;i<l;i++)

{

if(s[i]>='('&&s[i]<='+'||s[i]=='-'||s[i]=='/'||s[i]=='('||s[i]==')')

{ sv[j++]=s[i]; sv[j++]=' '; continue;}

else

{

sv[j++]=s[i];

while(operand_true(s[++i])==1&&s[i]!='\0')

sv[j++]=s[i];

sv[j++]=' ';

}

i--;

}

sv[j]='\0';

}

//--------------------------------------------------------------------------

void Stack::postfix()

{

int i=0,j=0,pr=0;

for(i;i<strlen(s);i++)

{

if(s[i]==' ') {sv[j++]=s[i]; continue;}

if(s[i]>='('&&s[i]<='+'||s[i]=='-'||s[i]=='/')

{

switch(s[i])

{

case '(':

{

if(!t1) {first1(s[i]);}

else {push1(s[i]);}

break;

}

case '*':

case '/':

{

if(!t1) {first1(s[i]); break;}

pr=prioritet_stack();

if(pr==3||pr==1) {push1(s[i]); break;}

else

{

while(pr==2&&t1)

{

sv[j++]=pop1();

if(t1) pr=prioritet_stack();

}

}

if(t1) {push1(s[i]); break;}

else {first1(s[i]); break;}

}

case '+':

case '-':

{

if(!t1) {first1(s[i]); break;}

pr=prioritet_stack();

if(pr==3) {push1(s[i]); break;}

else

{

while(pr<3&&t1)

{

sv[j++]=pop1();

if(t1) pr=prioritet_stack();

}

}

if(t1) {push1(s[i]); break;}

else {first1(s[i]); break;}

}

case ')':

{

pr=prioritet_stack();

while(pr!=3)

{

sv[j++]=pop1();

pr=prioritet_stack();

}

sv[j]= pop1();

}

}

}

else {sv[j++]=s[i]; continue;}

}

if(t1){ while(t1) sv[j++]=pop1();}

sv[j]='\0';

strcpy(s,sv);

}

//-------------------------------------------------------------------------

float Stack::calc()

{

int i=0,j=0,l=strlen(s);

char sc[10];

float a,b;

for(i;i<l;i++)

{

if(s[i]==' ') continue;

else

if(s[i]=='+'||s[i]=='-'||s[i]=='*'||s[i]=='/')

{

a=pop2();

b=pop2();

switch(s[i])

{

case '+': {a=a+b; break;}

case '-': {a=b-a; break;}

case '*': {a=a*b; break;}

case '/': {a=b/a; break;}

}

if(!t2) {first2(a); }

else {push2(a); }

}

else

{

while(operand_true(s[i])&&s[i]!='\0')

{

sc[j++]=s[i];

i++;

}

sc[j]='\0';

a=atof(sc);

j=0;

if(!t2) {first2(a);}

else {push2(a); }

}

}

return pop2();

}

//---------------------------------------------------------------------------------------------------

В файле реализации LR_5.cpp модуля LR_5 разместим обработчики событий – создание формы и щелчки на разделах меню Новое, Преобразование, Преобразование и вычисление, Выход с именами соответственно FormCreate, N2Click, N3Click, N4Click, N6Click. Заметим, что обработчик FormCreate можно вызвать двойным щелчком на форме.

Файл реализации LR_5.cpp модуля LR_5.

//---------------------------------------------------------------------------

#include <vcl.h>

#pragma hdrstop

#include "LR_5.h"

#include "f_5.h"

//---------------------------------------------------------------------------

#pragma package(smart_init)

#pragma resource "*.dfm"

TForm1 *Form1;

//---------------------------------------------------------------------------

AnsiString

S1="В выражении есть неверные операнды! Проверьте правильность записи.",

S2="В выражении не хватает скобки! Проверьте правильность записи.",

S3="В выражении лишние скобки! Проверьте правильность записи.",

S4="В выражении недостаточно операндов! Проверьте правильность записи.",

S5="В выражении недостаточно знаков операций! Проверьте правильность записи.";

//---------------------------------------------------------------------------

void Stack::out_err_code()

{ switch(err_code)

{

case bad_operands: {ShowMessage(S1); break;}

case few_brackets: {ShowMessage(S2); break;}

case much_brackets: {ShowMessage(S3); break;}

case few_operands: {ShowMessage(S4); break;}

case few_operators: {ShowMessage(S5); break;}

};

}

//---------------------------------------------------------------------------

__fastcall TForm1::TForm1(TComponent* Owner)

: TForm(Owner)

{

}

//---------------------------------------------------------------------------

Stack S;

void __fastcall TForm1::FormCreate(TObject *Sender)

{

Edit1->Text="";

Edit2->Text="";

Edit3->Text="";

Edit4->Text="";

Edit5->Text="";

Edit6->Text="";

Edit7->Text="";

Edit8->Text="";

}

//--------------------------------------------------------------------------

void __fastcall TForm1::N2Click(TObject *Sender)

{

Edit1->Text="";

Edit2->Text="";

Edit3->Text="";

Edit4->Text="";

Edit5->Text="";

Edit6->Text="";

Edit7->Text="";

Edit8->Text="";

Edit1->SetFocus();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::N3Click(TObject *Sender)

{

Edit2->Text="";

Edit3->Text="";

Edit4->Text="";

Edit5->Text="";

Edit6->Text="";

Edit7->Text="";

Edit8->Text="";

S.Stack_init();

S.s=(Edit1->Text+'\0'+'\0').c_str();

S.check();

if(S.err_code==all_true)

{

Edit2->Text=S.s;

S.bspaces();

S.s=S.sv;

Edit5->Text=S.s;

S.postfix();

Edit3->Text=S.s;

S.s=(Edit5->Text+'\0'+'\0'+'\0').c_str();

S.revers_before();

Edit6->Text=S.s;

S.postfix();

Edit7->Text=S.s;

S.revers_after();

Edit4->Text=S.s;

}

else

S.out_err_code();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::N4Click(TObject *Sender)

{

Edit2->Text="";

Edit3->Text="";

Edit4->Text="";

Edit5->Text="";

Edit6->Text="";

Edit7->Text="";

Edit8->Text="";

S.Stack_init();

S.s=(Edit1->Text+'\0'+'\0').c_str();

S.check();

if(S.err_code==all_true)

{

Edit2->Text=S.s;

S.bspaces();

S.s=S.sv;

Edit5->Text=S.s;

S.postfix();

Edit3->Text=S.s;

S.s=(Edit5->Text+'\0'+'\0'+'\0').c_str();

S.revers_before();

Edit6->Text=S.s;

S.postfix();

Edit7->Text=S.s;

S.revers_after();

Edit4->Text=S.s;

S.s=(Edit3->Text+'\0'+'\0'+'\0').c_str();

float result=S.calc();

Edit8->Text=FloatToStr(result);

}

else

S.out_err_code();

}

//---------------------------------------------------------------------------

void __fastcall TForm1::N6Click(TObject *Sender)

{

exit(0);

}

//---------------------------------------------------------------------------

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

Здесь программирование начинается с составления списка действий, которые будут доступны пользователю через разделы меню, инструментальные панели, кнопки и другие элементы управления. При программировании этот список реализуется в данном случае компонентом ActionList, обеспечивающим диспетчеризацию действий. Редактор диспетчера действий ActionList позволяет сформировать список действий, написать обработчики (если их еще нет), выполняющие задуманные действия, задать основные свойства будущих интерфейсных элементов – пиктограммы, надписи, быстрые кнопки, тексты подсказок и т.п.

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

Интерфейсные компоненты действий обычно должны содержать поясняющие их изображения. Изображения собираются в списке изображений – компоненте ImageList. Для нестандартных действий (наш случай) изображения загружаются в ImageList пользователем. А для стандартных действий они загружаются автоматически по мере формирования списка в диспетчере действий ActionList.

Диспетчеризация действий на основе компонента ActionList.

  1. Перенесите на форму со страницы Стандарт компонент ActionList1. Перенесите также со страницы Win32 компонент ImageList1 и сошлитесь на него в свойстве Images компонента ActionList1.

  2. Загрузите в компонент ImageList1 четыре изображения. Они загружаются в процессе проектирования с помощью редактора списков изображений. Окно редактора вызывается двойным щелчком на компоненте ImageList1 или щелчком правой кнопки мыши и выбором команды контекстного меню Редактор ImageList. В окне редактора Образы можно добавить в списки изображение (кнопка Добавить), удалить изображение из списка кнопкой Удалить, очистить весь список кнопкой Очистить. При добавлении изображения в список, которое начинается с нажатия кнопки Добавить, открывается окно открытия файлов изображений, в котором можно выбрать нужный файл. Множество изображений, размещаемых обычно на кнопках, содержится в папке …\Program Files\Common Files\Borland Shared\Images\Buttons. Следует помнить, что размер всех изображений в списке должен быть одинаковым. Как правило, это размер, используемый для пиктограмм в меню, списках, кнопках. При добавлении в список изображений для кнопок надо иметь в виду, что они часто содержат не одно, а два и более изображений. В этих случаях после выбора имени файла изображений при щелчке на кнопке Открыть задается вопрос: Bitmap dimensions forare greater then imagelist dimensions. Separate intoseparate bitmaps?” (“Размерность изображения … больше размерности списка. Разделить на … отдельные изображения?”). Если ответить отрицательно, то все изображения уменьшатся в горизонтальном размере и лягут как одно изображение. Использовать его в дальнейшем будет невозможно. Поэтому на заданный вопрос надо ответить положительно. Тогда загружаемая битовая матрица автоматически разделится на отдельные изображения, а затем те из них, которые не нужны, удаляют. Каждое загруженное в список изображение получает индекс. Именно на эти индексы впоследствии ссылаются в соответствующих свойствах разделов меню, списков, кнопок и т.д., когда надо загрузить в них то или иное изображение. Чтобы изменить последовательность изображений в списке, перетаскивают изображение мышью на новое место. Итак, изображения добавляют из файлов clear, fontbold, tools, dooropen. Ненужные изображения в окне Образы выделяют щелчком мыши и удаляют, а когда все четыре изображения с соответствующими номерами будут находиться в окне, их загружают нажатием клавиши Ок.

  3. Сделайте на компоненте ActionList1 двойной щелчок, чтобы попасть в Редактор Действий (окно Редактирование Form1->ActionList1), позволяющий вводить и упорядочивать действия. Колонка Категории: не имеет отношения к проектированию данного приложения. Щелчок правой кнопкой мыши или щелчок на маленькой кнопке со стрелкой вниз правее первой быстрой кнопки окна редактирования позволяет выбрать одну из команд: Новое действие или Новое стандартное действие. Первая из них относится к вводу нового действия любого типа. Будем пользоваться только командой Новое действие. Выберите эту команду четыре раза. В колонке Действия: появятся имена действий по умолчанию: Action1, Action2, Action3, Action4.

  4. Выделите Action1. В Инспекторе Объектов указанным ниже свойствам объекта действия Action1 присвойте следующие значения: CaptionНовое, Hintочистка, ImageIndex0, NameANew, ShortCutCtrl+A. Для Action2: CaptionПреобразование, Hintпреобразование, ImageIndex1, NameAMod, ShortCutCtrl+B. Для Action3: CaptionПреобразование и вычисление, Hintпреобразование и вычисление, ImageIndex2, NameARun, ShortCutCtrl+C. И для Action4: CaptionВыход, Hintвыход, ImageIndex3, NameAExit, ShortCutCtrl+D.

  5. На странице событий Инспектора Объектов для каждого действия определено три события: OnExecute, OnUpdate и OnHint. Событие OnExecute возникает в момент, когда пользователь инициализировал действие, например, щелкнув на компоненте (разделе меню, кнопке), связанном с данным действием. Обработчик этого события должен содержать процедуру, реализующую данное действие. Событие OnUpdate периодически возникает в промежутках между действиями. Возникновение этих событий прекращается только во время реализации события или во время, когда пользователь ничего не делает и компьютер находится в состоянии ожидания действий. Обработчик события OnUpdate может содержать какие-то настройки, подготовку ожидаемых дальнейших действий или выполнение каких-то фоновых операций. Событие OnHint возникает в момент, когда на экране отображается ярлычок подсказки в результате того, что пользователь задержал курсор мыши над компонентом, инициализирующим событие. Наличие в объекте действия событий OnUpdate и OnHint расширяет возможности по проектированию приложения. В выпадающем списке события OnExecute содержатся значения FormCreate, N2Click, N3Click, N4Click, N6Click, т.е. имена написанных обработчиков событий – создание формы и щелчки на разделах меню Новое, Преобразование, Преобразование и вычисление, Выход. Для действия Anew примите N2Click, AMod - N3Click, ARun - N4Click, AExit - N6Click.

  6. В свойство Images компонента MainMenu1 внесите ImageList1. Двойным щелчком на компоненте MainMenu1 перейдите в окно Form1-> MainMenu1 Конструктора Меню. В свойство Action разделов Новое, Преобразование, Преобразование и вычисление, Выход внесите соответственно значения Anew, AMod, ARun, AExit. Как показывает Инспектор Объектов, при этом в разделы меню переносятся свойства соответствующего объекта действия.

  7. Со страницы Win32 перенесите на форму инструментальную панель - компонент ToolBar. По умолчанию он расположится вверху, поскольку его свойство Align по умолчанию равно alTop. Установите Align=alNone, чтобы можно было придать любую форму и расположить ее в любом месте.

  8. В свойство Hint впишите инструментальная панель, в свойство Images внесите ImageList1, в ShowHinttrue. Щелкните правой кнопкой мыши на компоненте ToolBar1 и из всплывшего меню выберите команду Новая кнопка. В свойство Action кнопки внесите ANew, а в свойство ShowHinttrue. Повторите эту команду еще для трех кнопок, внося в свойство Action соответственно AMod, ARun, AExit, в свойство ShowHinttrue. Отметим, что свойства и обработчики событий объекта действия будут перенесены на соответствующие кнопки инструментальной панели.

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]