DIPLOM (716574), страница 7
Текст из файла (страница 7)
2.6.4.2 ФОРМИРОВАНИЕ МЕНЮ И СТРОКИ СТАТУСА.
Теперь нужно создать основные элементы программы - строку меню и строку состояния. Для этого я модифицировал стандартное поведение объекта SKLVKS. Я перекрыл (переопределил) унаследованные от TApplication методы InitStatusLine и InitMenuBar. Метод InitStatusLine я перекрыл так, чтобы программа в строке состояния вывела подсказки : выхода из программы, справка и меню. При нажатии мышкой или при нажатии горячей клавишу на соответствующую надпись ваполнится связанная с ней процедура. Например при нажатии на F1 на экране появится сообщение о создании СУРКК или при нажатии на F10 активизируется строка меню. Метод InitMenuBar перекрал так, чтобы организовать меню для работы с данными. (см. рис 2)
USES APP,OBJECTS,MENUS,DRIVERS,VIEWS;
Const
cmPrnSklad = 200;
cmSklad = 201;
cmZak = 203;
cmPriceLst = 204;
cmHelp_About = 205;
cmPrint = 206;
cmPrihod = 207;
cmSbros = 208;
cmNext = 209;
cmMore = 213;
cmSKL = 214;
cmDostup = 215;
cmDobavka = 216;
cmRekviz = 217;
cmKurs = 218;
cmTemp = 219;
cmPriceList = 220;
cmSdelka = 221;
cmPrih = 222;
cmVozvrat = 223;
cmKorPrihod = 224;
cmDolgi = 225;
cmUdal = 226;
cmMoney = 227;
cmArchive = 228;
Type
TSklVks = object(TApplication)
Procedure InitStatusLine ; Virtual;
Procedure InitMenuBar ; Virtual;
End;
Procedure TSklVks.InitStatusLine; { создает строку статуса }
var
R: Trect;
Begin
GetExtent(R);
R.A.Y:=pred(R.B.Y); { координаты строки статуса }
StatusLine:=New(PStatusLine,Init(R,NewStatusDef(0,$ffff,
NewStatusKey(' ~ALT-X~-Конец работы',kbAltX,cmQuit,
NewStatusKey(' ~F1~-Справка',kbf1,cmHelp_About,
NewStatusKey(' ~F10~-Меню',kbf10,cmMenu,
nil))),nil)));
END;
Procedure TSklVks.InitMenuBar; { Создает строку меню }
var
R: Trect;
Begin
GetExtent(R);
R.B.Y :=succ(R.A.Y); { координаты строки меню }
MenuBar:=New(PMenuBar,Init(R,NewMenu(NewSubMenu('~Д~анные',hcNoContext,
NewMenu(
NewItem('~С~клад',' ',kbNokey,cmSklad,hcNoContext,
NewItem('С~д~елки',' ',kbNoKey,cmSdelka,hcNoContext,
NewItem('~П~риходы',' ',kbNoKey,cmPrih,hcNoContext,
NewItem('Дол~г~и',' ',kbNoKey,cmDolgi,hcNoContext,
NewItem('Выруч~к~а',' ',kbNoKey,cmMoney,hcNoContext,
NewLine(
NewItem('~В~ыход','ALT-X',kbAltX,cmQuit,hcNoContext,nil)))))))),
NewSubMenu('~К~лиент',hcNoContext,(NewMenu(
NewItem('~П~родажа','',kbNoKey,cmZak,hcNoConText,
NewItem('~В~озврат','',kbNoKey,cmVozvrat,hcNoConText,
nil)))),
NewSubMenu('~П~оставщик',hcNoContext,NewMenu(
NewItem('Новый при~х~од','',kbNoKey,cmPrihod,hcNoContext,
NewItem('~К~орректировка прихода','',KbNoKey,cmKorPrihod,hcNoContext,
nil))),
NewSubMenu('Пе~ч~ать',hcNoContext,NewMenu(
NewItem('~О~тчет о наличии товара',' ',kbNoKey,cmPrnSklad,hcNoContext,
NewItem('Прайс ~л~ист',' ',KbNoKey,cmPriceList,hcNoContext,
nil))),
NewSubMenu('~А~рхив',hcNoContext,NewMenu(NewItem('~Р~абота с архивом',
' ',kbNokey,cmArchive,hcNoContext,nil)),
NewSubMenu('~У~становки',hcNoContext,NewMenu(
NewItem('~П~ароль',' ',kbNoKey,cmDostup,hcNoContext,
NewItem('Рекви~з~иты',' ',kbNoKey,cmRekviz,hcNoContext,
NewItem('Кур~с~ доллара',' ',kbNoKey,cmKurs,hcNocontext,
nil)))),
NewSubMenu('~И~нформация',hcNoContext,NewMenu(
NewItem('О Скла~д~е ... ','',kbNokey,cmHelp_About,hcNoContext,
nil)),
nil))))))))));
end;
Var
SKLVKS : TSKLVKS;
BEGIN { Основная программа }
SklVks.Init;
SklVks.Run;
SklVks.Done;
END. { Конец основной программы }
(рис 2)
2.6.4.3 ОБРАБОТКА КОМАНД
Теперь нужно сделать так, чтобы при выборе какого-либо пункта меню выполнялась соответсвующая процедура. При выборе пунктов меню генерирует событие, которое обрабатывается подпрограммой - обработчиком событий. Для этого ч перекрыл стандартный обработчик событий HandleEvent объекта TApplication. Для этого в описании объекта TSklVks добавил еще одну строку ...
Type
TSklVks = Object(TApplication)
......
Procedure HandleEvent(var Event : Tevent); virtual;
End;
и поместил в раздел объявлений текс новой подпрограммы :
Procedure TSklVks.HandleEvent(var Event : TEvent);
Begin
TApplication.HandleEvent(Event);
if Event.What = evCommand then
case Event.Command of
cmPrnSklad : Begin
PrintSklad;
End;
cmSklad : begin
Sklad;
end;
cmZak : Begin
Zak;
End;
cmHelp_About : Begin
Help_About;
End;
cmPrihod : Begin
Prihod;
End;
cmPrih : Begin
Prih;
End;
cmDostup : begin
Dostup;
end;
cmRekviz : begin;
rekviz;
end;
cmKurs : Begin
Kurs;
end;
cmPriceList : Begin
GetDate(yyyy,mm,dd,ww);
PriceList(dd,mm,yyyy);
ClearEvent(Event);
end;
cmSdelka : Begin
Sdelki;
End;
cmVozvrat : Begin
Vozvrat;
End;
cmKorPrihod : Begin
KorPrihod;
End;
cmDolgi : Begin
Dolgi;
End;
cmMoney : Begin
Money;
End;
cmArchive : Begin
Arc_;
End;
else
ClearEvent(Event);
end;
ClearEvent(Event)
End;
2.6.4.4 ПРОГРАММИРОВАНИЕ ДИАЛОГОВЫХ ЗАПРОСОВ
В обработчике событий TSklVks.HandleEvent я предусмотрел вызов нескольких процедур, с помощью которых реализуются конкретные действия. Начну с процедуры Prih. Ее задача - ввести данные о новом приходе. Очевидно, что данные будут храниться в файле, поэтому опишу сразу структуру данных. Данные выглядят в виде записи, которые состоят из полей. Например структура данных для приходов выглядит следующим образом :
(* Структура приходов *)
Type PPP = record
Number : LongInt; { номер прихода}
FirmName : String[22]; { фирма поставщик }
Date : String[10]; { дата прихода }
Kurs : Real; { курс доллара ЦБ РФ на день прихода}
TotalItems : LongInt; { кол-во пришедших наименований}
SebSumma : Real; { общая сумма прихода }
End;
(* Структура приходов для наименования}
Type PPPItems = Record
Number : LongInt; {ноиер наименования }
PrihodNum : LongInt; {номер прихода}
SkladNum : LongInt; {номер наименования на складе}
Name : String[lpname]; {наименование}
Rasf : String[lprasf]; {расфасовка}
Box : Integer; {кол-во штук в упаковке}
Kolvo : LongInt; {кол-во поступившего наименования}
SebPrice : Real; {себестоимость наименования}
Price : Real; {стоимость наименования}
SellTimes : Boolean; {зарезервировано}
End;
Эти строки находятся в модуле SKLTYPES.PAS. В нем же находится описание всех структур данных, а так же их связь с файлами и основной программой :
Var {ТИП ДАННЫХ}
PrihodData : PPP;
PrihodItemsData : PPPItems;
....{ТИП ДАННЫХ В ФАЙЛЕ}
PrihodFile : File of PPP;
PrihodItemsFile : File of PPPItems;
....
Теперь, надо ввести данные. Для этого сначала появляется панель диалога для ввода даты прихода, курса прихода и реквизитов фирмы поставщика. Ее я создавал при помощи небольшой программы Dialog Designer 4.0. При создании панелей диалога при помощи это программы генерируется модульный файл в котором реализован код для отображения окна, его закрытия, так же содержится обработчик событий.
Ниже приведу текст модуля, cодержащего код для создания диалогового окна.
unit PRIHOD1;
interface
uses Drivers, Objects, Views, Dialogs, Validate;
type
PrihodDataRec = record
Field1 : String[10];
Field3 : String[13];
Field2 : String[22];
end;
PPrihodDataRec = ^PrihodDataRec;
{ TPrihodDataDialog }
PPrihodDataDialog = ^TPrihodDataDialog;
TPrihodDataDialog = object(TDialog)
constructor Init;
constructor Load(var S: TStream);
procedure HandleEvent(var Event: TEvent); virtual;
procedure Store(var S: TStream);
function Valid(Command : word): boolean; virtual;
destructor Done; virtual;
end;
Var
PRD : PrihodDataRec;
Const
RPrihodDataDialog : TStreamRec = (
ObjType: 12345; {= 100 here!!}
VmtLink: Ofs(Typeof(TPrihodDataDialog)^);
Load : @TPrihodDataDialog.Load;
Store : @TPrihodDataDialog.Store);
implementation
{ TPrihodDataDialog }
constructor TPrihodDataDialog.Init;
var
R: TRect;
Control : PView;
begin
R.Assign(13, 3, 66, 17);
inherited Init(R, 'Приход / Ввод данных');
Flags := Flags and not wfMove;
R.Assign(24, 3, 36, 4);
Control := New(PInputLine, Init(R, 10));
Insert(Control);
PInputLine(Control)^.Validator := New(PPXPictureValidator, Init('{##}/{##}/{####}', true));
R.Assign(5, 3, 24, 4);
Insert(New(PLabel, Init(R, 'Дата : ', Control)));
R.Assign(24, 5, 39, 6);
Control := New(PInputLine, Init(R, 13));
Insert(Control);
PInputLine(Control)^.Validator := New(PPXPictureValidator, Init('*#[.#][#]', False));
R.Assign(5, 5, 24, 6);
Insert(New(PLabel, Init(R, 'Курс прихода : ', Control)));
R.Assign(24, 7, 48, 8);
Control := New(PInputLine, Init(R, 22));
Insert(Control);
R.Assign(5, 7, 24, 8);
Insert(New(PLabel, Init(R, 'Фирма поставщик : ', Control)));
R.Assign(7, 10, 18, 12);
Control := New(PButton, Init(R, '~С~брос', cmCancel, bfNormal));
Insert(Control);
R.Assign(23, 10, 41, 12);
Control := New(PButton, Init(R, '~Н~аименования', cmOK, bfDefault));
Insert(Control);
R.Assign(37, 3, 51, 4);
Control := New(PStaticText, Init(R, '[ ДД/ММ/ГГГГ ]'));
Insert(Control);
SelectNext(False);
end;
constructor TPrihodDataDialog.Load(var S: TStream);
begin
inherited Load(S);
end;
procedure TPrihodDataDialog.HandleEvent(var Event: TEvent);
begin
(*---
if Event.What = evMessage then
case Event.Command of
end; --*)
inherited HandleEvent(Event);
(*---
if Event.What = evMessage then
case Event.Command of
end; --*)
end;
procedure TPrihodDataDialog.Store(var S: TStream);
begin
inherited Store(S);
end;
function TPrihodDataDialog.Valid(Command : word): boolean;
var
Result : boolean;
begin
Result := inherited Valid(Command);
Valid := Result;
end;
destructor TPrihodDataDialog.Done;
begin
inherited Done;
end;
end.
Для отображения этого диалогового окна в процедуре PRIH испльзовался следующий код :
PRD.Field1:=ShowDate; { Дата прихода - текущая дата}
Str(GetKurs:-1:2,PRD.Field3); { Курс прихода - текущий курс }
FillChar(PRD.Field2[1],22,' '); {Онулить фирму поставщика}
c1:=ExecuteDialog(New(PPrihodDataDialog,Init),@PRD);1 { Ввести на экран панель диалога}
После ввода курса, даты и фирмы поставщика нужно ввести собственно наименования. Для этого я создал диалоговое окно (см. модуль PRIH2.PAS), где вводится информации о наименовании (название, расфасовка, стоимость, себестоимость и т.д.). (см. рис. 3)
(рис.3)
Введя данные, их надо сохранить. Чтобы это сделать надо сначала открыть файл, затем в его конец записать данные и в конце этот файл закрыть. Это делается приблизительно так ( подробно см. файл FIRMA.PAS) :
OpenPrihodFile; { Процедура открытия файла см.модуль SklFiles.Pas}
Seek(PrihodFile,FileSize(PrihodFile)-1);
Write(PrihodFile,PrihodData);
ClosePrihodFile; { см. модуль SklFiles.Pas}
Если нажимается кнопка СБРОС, то вызывается процедура сброса прихода в которой все задействованные файлы данных усекаются до предыдущей длина (в начале процедуры PRIH запоминаются текущие длины файлов) при помощи стандартной процедуры TRUNCATE.
После успешного ввода данных появляется запрос о печати приходной накладной. Печать осуществляется стандартными средствами (см. процедуры PrintPrihodNakl и PrintEndOfPrihodNakl в модуле SklUnit). С помощью константы LST, компьютер связывается с печатающим устройством на LPT1, затем процедурами Writeln(LST,‘строка для печати’) данные выводятся на принтер. Все введенные данные помещаются в файлы данных : SKLAD.001 (Товар на складе) , PRIHOD.001 (Заголовки приходов), PRIHOD.002 (Пришедшие наименования). Затем пользователь получает доступ к следующим командам меню : Данные-Склад, Данные-Приходы, Печать-Прайс-Лист, Печать-Отчет о наличии товара на складе, Клиент-Продажа. Основной из вышеперечисленных команд является Клиент-Продажа. При помощи этой команды пользователь должен выписать накладную по заказу клиента. Реализовал эту команду так : Появляется диалоговое окно со списком наименований, имеющихся на складе (В нем пользователь выбирает продаваемые наименования и их количества). Затем при нажатии на кнопку ОПЛАТА появляется окно со списком всех выбранных наименований (накладная) в котором предоставляется возможность отредактировать введенные данные (изменить количество каждого наименования, его стоимость и курс доллара). Далее после нажатия на ОПЛАТА на экране появляется диалоговое окно для ввода следующей информации : реквизиты клиента, форма сделки (реализация), округление суммы накладной, дата накладной. После нажатия на ВЫПИСАТЬ НАКЛАДНУЮ у пользователя программы спрашивает, нужно ли печатать накладную и если товар дается клиенту не на реализацию, то спрашивается, нужно ли печатать приходный кассовый ордер. Все введенные данные помещаются в файлы данных : SDELKA.001 (Заголовки сделок), SDELKA.002 (Наименования сделок), в файле SKLAD.001 делаются соответствующие изменения по количеству оставшегося товара.
Для реализации диалогового окна со списком я создал коллекцию строк наименований имеющихся на складе, причем если товара на складе не осталось то это наименование не помещаеся в коллекцию.
Data1:=New(PStrSor,Init(10,1)); {Указатель на коллекцию }
For N:=0 to FileSize(DataFile)-1 do {Каждую позицию проверить, если нулевая то не вносить в коллекцию)
begin {1}
Seek(DataFile,n);