2.6. СРЕДСТВА РАЗРАБОТКИ

2.6.1 КОМПИЛЯТОР BORLAND PASCAL 7.0

Компилятор Borland Pascal 7.0 позволяет создавать программы, которые могут выполнятся в реальном и защищенном режимах DOS и в среде WINDOWS. Таким образом, эту версию компилятора могут использовать программисты, на любом типе ЭВМ, включая IBM PC/XT. Напомню, что с шестой версии компилятора BP введена такая новинка, как объектно-ориентированная библиотека Turbo Vision 2.0, поставляемая вместе с компилятором, для создания DOS приложений.  

2.6.2. ОБЪЕКТНО-ОРИЕНТИРОВАННАЯ БИБЛИОТЕКА TURBO VISION

Новая версия объектно-ориентированной библиотеки для создания DOS-приложений TURBO VISION 2.0 содержит ряд новых объектов и изменений : объект TValidator и объекты построенные на его основе, используются совместно со строками ввода для проверки введенных данных. Реализованы объекты для проверки вхождения данных в указанный диапазон, ограничения вводимых данных, но самое ценное - это объекты, позволяющие вводить информацию на основе шаблонов, задаваемых в формате Paradox и dBASE.

И все же, что такое Turbo Visoin 2.0 ? TV - это мощная объектно-ориентированная оболочка для оконных программ. Borland International создала Turbo Vision, чтобы убереч программистов от бесконечного создания оболочек для построения прикладных программ.

Turbo Vision - это объектно-ориентированная библиотека, включающая :

•  многократные перекрывающиеся окна с изменяемыми размерами;

•  выпадающие меню;

•  поддержку мыши;

•  диалоговые окна;

•  кнопки, полосы скроллинга, окна ввода, зависимые и независимые кнопки;

Используя TV можно разрабатывать программы с незначительными усилиями.

2.6.3. ЭЛЕМЕНТЫ TURBO VISION

Turbo Vision - это объединение видимых элементов, событий и невидимых объектов.

Видимый элемент - это любой элемент программы, который виден на экране, и все эти элементы являются объектами. Поля, рамки окон, полосы скроллинга, полосы меню, диалоговые окна - это все видимые элементы. Видимые элементы могут объединяться для формирования более сложных элементов, таких как окна и диалоговые окна. Эти наборы видимых элементов называются группами, и они работают вместе так, как если бы это был один видимый элемент. Основными видимыми элементами являются следующие :

•  Панель экрана - это объект TDesktop, создающий фоновое изображение рабочей панели экрана. Заполнение панели экрана осуществляется другими видимыми элементами, такими как TWindow, TDialog и т.п. Обычно владельцем группы TDesktop является объект TApplication или его потомки.

•  Окна. Для создания и использования окон в Turbo Vision предусмотрен объект TWindow. Обычно этот объект владеет объектом TFrame и поэтому очерчивается прямоугольной рамкой со стандартными кнопками изменения размера и закрытия. Если окно имеет несколько видимых элементов, его обработчик событий интерпретирует нажатие на клавиши Tab и Shift-Tab как команду активизации следующего (предыдущего) видимого элемента.

•  Диалоговые окна . Объект TDialog порожден от TWindow и предназначен для реализации взаимодействия с пользователем. В отличие от TWindow диалоговое окно не может изменять свой размер, но может перемещаться по экрану. Его обработчик событий генерирует команду cmCancel в ответ на нажатие клавиши Esc (или воздействие мыши на кнопку закрытия) и команду cmDefault в ответ на нажатие Enter.

•  Кнопки. Объект TButton - это прямогугольник с надписью, имитирующий кнопку панели управления. Обычно TButton является элементом группы TDialog и нажатие на кнопку иницирует событие, связанное с какой-либо стандартной коммандой или командой пользователя.

•  Строки ввода . Для ввода различных текстовых строк с клавиатуры используется объект TInputLine. Использование этого объекта дает в распоряжение пользователя мощные возможности встроенного редактора, обрабатывающего алфавитно-цифровые клавиши, клавиши перемещения курсора влево/вправо, а также клавиши Backspace, Delete, Insert, Home, End.

•  Просмотр списков . Абстрактный объект TListViewer предоставляет в распоряжение программиста средства просмотра списка строк и выбора из этого списка нужной строки.

•  Статический текст . Объект TStaticText - это видимый объект, используемый для вывода текстовых сообщений. В отличие от строк, созданных непосредственным выводом с использованием стандартной процедуры Writeln, текстовая строка объекта TStaticText может входить в группу видимых элементов (например диалоговое окно) и управляться этой группой. Статический текс игнорирует любые события, посланные к нему.

Событие - это что-то, на что программа должна отреагировать. События могут приходить от клавиатуры, от мышки или от других частей TV. Например, нажата клавиша - это событие такое же, как и нажатие кнопки мыши. События поступают в очередь внутри TV по мере их появления и затем обрабатываются обработчиком событий. Объект Tapplication, который является ядром каждой программы на TV содержит обработчик событий.

Например, клавиша F1 вызывает диалоговое окно, содержащее подсказку о создании программы.

Невидимые объекты - это любые другие объекты программы, отличные от видимых элементов. Они невидимы, поскольку сами ничего не выводят на экран.

Они производят вычисления, связь с периферией и выполняют другую работу прикладной программы. Когда невидимому объекту необходимо вывести что-либо на экран, он должен связаться с видимым элементом.

Для создания системы управления работой коммерческой компании (СУРКК) использовалась стандартная объектно-ориентированную библиотека TURBO VISION. Именно она, поскольку без особых усилий была создана диалоговая программа с пользовательским интерфейсом высокого уровня, облегчившая взаимодействие пользователя с данными.

2.6.4 ОПИСАНИЕ ПРОЦЕССА РАЗРАБОТКИ.

2.6.4.1 НАЧАЛО СОЗДАНИЯ.

Работа большинства прикладных программ проходит в три этапа : подготовка к работе, собственно работа и, наконец, ее завершение. В случае с СУРКК к подготовительному этапу можно отнести такие действия, как анализ существования файлов данных и его подготовка к работе, проверка легальности копии и т.п.. На этапе завершения, необходимо произвести действия по сохранению файлов данных. Все остальные действия относятся к среднему этапу. С учетом этого можно написать простейшую программу :

BEGIN

{Подготовка к работе}

{Работа}

{Завершить работу}

END.

Если попытаться выполнить эту программу, ничего не произойдет. Так обстоит дело с Borland Pascal'ем, но не так в Turbo Vision ! Для любой прикладной программы Turbo Vision создает минимальную программную реализацию, которую затем можно постепенно наращивать в ходе детализации программы. Вот начальный вариант программы с использованием Turbo Vision.

Uses App;

Var

SklVks : TSklVks;

Begin

SklVks.Init;

SklVks.Run;

SklVks.Done;

End.

В этой программе объявлено использование стандартного для Turbo Vision модуля APP (от Application - прикладная программа). Такое объявление открыло доступ к мощным возможностям Turbo Vision. Затем объявили экземпляр объекта TApplication, т.е. объединение данных и методов обработки этик данных (процедур, функций, конструкторов, деструкторов). В объекте TApplication предусмотрены методы INIT, RUN и DONE. Вызов этих методов и составляет исполняемую часть программы. Если запустить эту программу, то на экран появится изображение (см. рис 1) :

(рис 1)

 

Как видно, даже простейшая программа “знает”, как создать экран, распознать команду ALT-X и может работать с мышью. Совсем не плохо для трех исполняемых операторов, не так ли ? Такие возможности доступны потому, что в объекте TApplication предусмотрены соответствующие методы.

Простейшая программа не может выполнять никаких других действий, кроме уже перечисленных, так как именно эти действия запрограммированы в методах Init и Run объекта TApplication. В ходе их выполнения на экране создается изображение, имеющее три зоны : верхняя строка (строка меню), нижняя строка (строка статуса) и вся остальная часть (рабочая область).

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. При создании панелей диалога при помощи это программы генерируется модульный файл в котором реализован код для отображения окна, его закрытия, так же содержится обработчик событий.

Ниже приведу текст модуля, содержащего код для создания диалогового окна.

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; {<--- Insert a unique number >= 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); { Ввести на экран панель диалога}

После ввода курса, даты и фирмы поставщика нужно ввести собственно наименования. Для этого я создал диалоговое окно (см. модуль 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);

Read(DataFile,Data); { Считываем данные }

val(Data.ProductOst,tempccc,code);

Str(Data1^.Count+1,Numm);

if tempccc=0 then goto ccc; { Если нулевая позиция, то не вносить в коллекцию }

o[0]:=chr(57);

FillChar(o[1],57,' ');

with data do

begin {Создание строки типа : Номер, Наименование, Расфасовка}

move(Numm[1],o[2],Length(Numm));

move(ProductName[1],o[succ(lpnum-1)+4],Length(Data.ProductName));

move(ProductRasf[1],o[succ(lpnum+lpname)+5],Length(Data.ProductRasf));

move(ProductNumber[1],o[50],Length(Data.ProductNumber));

end;

Data1^.Insert(NewStr(o)); {Помещаю ее в коллекцию строк}

ccc:

end; {1}

Для реализации списка строк в Turbo Vision предусмотрен объект TListBox. Это объект создает специальное окно скроллера с указателем на текущий элемент. Наименования я поместил в вышеописанную коллекцию строк, указатель на которую передал объекту с помощью метода TListBox.NewList.

Var

SCR : PScrollBar ;

LIST : PLitstBox;

.....

Begin

.....

RR.Assign(50,05,51,17); { Координаты скроллера }

Scr:=New(PscrollBar,Init(RR)); { Указатель на полосу скроллера }

Insert(Scr); { Создаем скроллер }

R.Assign(03,05,50,17); { Координаты окна со списком }

List:=New(PMyListBox,Init(R,1,scr)); {Указатель на окно со списком}

List^.NewList(Data1); {Связывание окна со коллекцией строк}

Insert(list); {Создаем окно со списком }

....

End;

Диалоговое окно выбора наименований выглядит следующим образом :

Перейду теперь к описанию процедуры Данные-Сделки. При выборе соответствующего пункта меню на экране появляется диалоговое окно выбора периода для просмотра сделок. В нем нужно ввести нижнюю и верхнюю границы периода.

После ввода при нажатии на кнопку ПОКАЗАТЬ ЗА ПЕРИОД разворачивается окно со списком сделок (накладных) относящихся к введенному периоду. Это реализованное следующим образом. При создании коллекции строк с накладными сравниваются дата сделки, нижняя и верхняя границы периода при помощи написанной прцедуоы DATECOMP из модуля DATES.PAS. Но для того, чтобы накладные располагались по порядку (по дате) мне пришлось перекрыть метод сортировки коллекции (см. модуль SKLSTR.PAS). После того, как создано диалоговое окно, пользователю предоставляется возможность распечатать выбранную накладную, соответствующую накладную по себестоимости и если накладная оплачена, то и приходный кассовый ордер.

2.6.4.5 ПРЕОБРАЗОВАНИЕ ДАННЫХ ПРИ ВЫВОДЕ ДОКУМЕНТОВ НА ПЕЧАТАЮЩЕЕ УСТРОЙСТВО.

В основном, вывод осуществляется стандартными процедурами Borland Pascal. Но например для печати приходного кассового ордера мне пришлось создать функцию для перевода суммы в слова (123 рубля в сто двадцать три рубля). Эта функция находится в модуле NUMSTR.PAS. Или для большей читабельности документов написал функцию для преобразования строки типа 1000000.00 в строку типа 1,000,000.00. Эта функция так же находится в модуле NUMSTR.PAS.

2.6.4.6 АРХИВИРОВАНИЕ ДАННЫХ .

Для того, чтобы в списке сделок не появлялись уже не нужные данные я написал подпрограмму для архивирования данных. При выборе команды меню АРХИВ-РАБОТА С АРХИВОМ на экране появляется диалоговое окно с двумя списками строк. В первом списке (СКЛАД) располагаются периоды сделок (месяц, год), которые доступны пользователю для просмотра, а во втором списке (АРХИВ) сделки которые находятся в АРХИВЕ. Для архивации периода сделок использовал следующий алгоритм: При выборе периода для архивации, программа проверяет каждую сделку на принадлежность к этому периоду. Ecли сделка попадает а него, то поле SDELKA.ARCHIVE устанавливается в TRUE. При выборе периода для деархивации прграмма устанавливает поля SDELKA.ARCHIVE соответствующих сделок в FALSE. Подпрограмма архивации также увеличивает быстродействие программы за счет уменьшения количества выводимых сделок. 

2.6.4.7 ВВОД УСТАНОВОК .

Для того, чтобы предотвратить использование данной программы лицами не имеющим разрешения ее использование был создана подпрограммы для ввода пароля. Пароль (и все установки) хранится в конфигурационном файле FIRMA.DAT, который имеет следующую структуру :

Type {Структура данных для конфигурационного файла}

ConfigFileStructure = record

CassName : String[22]; { ФИО Кассира }

BuhName : String[30]; { ФИО бухгалтера }

GenName : String[30]; { ФИО коммерческого директора }

UserName : String[30]; { ФИО пользователя }

Signature : String[10]; { Сюда пишется дата BIOS' а }

Reserved1 : String[10]; { }

Reserved2 : String[10]; { Зарезервировано }

Reserved3 : String[20]; { }

Password : String[10]; { Пароль }

FirmName : String[60]; { Реквизиты фирмы }

Kurs : Real; { Курс доллара }

end;

При начальном запуске пароль не установлен. При необходимости из меню УСТАНОВКИ-ПАРОЛЬ можно установить пароль. Опишу реализацию подпрограмму для его установки. Создается диалоговое окно со строкой ввода. Для того, чтобы привводе пароля на экране не отображались вводимые символы, был перекрыт метод TInputLine.HandelEvent так, что бы каждый введенный символ помещался в отдельную строку, а отображался ‘*' (звездочкой). Для детального просмотра алгоритма см. модуль PASSWORD.PAS. После введения пароля и нажатия на кнопку OK появляется диалоговое окно для проверки введенного пароля. Если оба введенных пароля совпадают, то он записывается в файл FIRMA.DAT в поле Password. Если они не совпадают, то пароль не устанавливается.

Анологично реализованы подпрограммы для ввода реквизитов и курса доллара.

Метод ExecuteDialog (введен в седьмой версии Borlan Pascal) очень удобен для отображения диалоговых окон, т.к. он осуществляет автоматическую вставку и получения данных в ходе создания и закрытия панели диалога.

2.6.4.8. ПАРОЛИРОВАНИЕ.

Для того, чтобы предотвратить доступ к данным я решил создать пароль, который запрашивался бы каждый раз при запуске программы. Для этого в записи ConfigFileStructure и добавил поле PassWord типа String[10];

 

Type

ConfigFileStructure = record

....

Password : String[10];

....

End;

 

Затем в меню УСТАНОВКИ добавил подменю УСТАНОВКИ-ПАРОЛЬ и связал с ним комманду cmDostup, которая вызывает процедуру ввода пароля Dostup из модуля SETUP.PAS. Эта процедура реализована так: На экране появляется диалоговое окно со строкой ввода :

Введите пароль . В ней вводится пароль и при нажатии на кнопку OK появляется следующее окно для проверки введенного пароля. Если во втором окне введенный пароль соответствует введенному паролю в первом окне, то этот пароль кодируется и записывается в файл FIRMA.DAT. Кодирование происходит следующим образом. Каждый символ пароля умножается на число (58+номер символа)*2. При запуске программы появляется диалоговое окно со сорокой ввода Введите пароль . Если введенный пароль в закодированном виде соответствует установленному закодированному паролю, то программа продолжает функционировать , а если не соответствуют, то выводится сообщение о не правильно введенном пароле и программа прекращает функционировать.

2.6.4.9. СТРУКТУРА БАЗ ДАННЫХ (БД).

Теперь рассмотрю структуру баз данных. Структура не является сложной, однако

она может содержать все данные, необходимые для данной системой и связь между разными БД осуществляется довольно простым путем.

Основной БД является БД, которая содержит информацию о наименованиях, имеющихся на складе (о количестве, о стоимости и т.д.). Она имеет следующую структуру :

Type

DataType = record { Структура складских данных}

ProductNumber : String[5]; { Номер }

ProductName : String[22]; { Наименование }

ProductRasf : String[10]; { Расфасовка }

PieceInBox : String[5]; { Кол - во штук в упаковке }

ProductPrice : String[12]; { Себестоимость }

ProductKol : String[12]; { Поставленное количество }

ProductFirm : String[22]; { Фирма поставщик }

ProductDate : String[l10]; { Дата прихода }

ProductOST : String[12]; { Осталось на складе }

ProductKurs : Real; { Курс прихода }

ProductSellPrice : Real; { Стоимость }

ProductVozvrat : LongInt; { Возврат }

end;

Var

Data : DataType;

DataFile : File of DataType; { Файл SKLAD.001}

Для записи (считывания) данных в (из) нее используется следующий алгоритм:

•  Открыть файл данных.

•  Поместить указатель положения в файле на нужную запись.

•  Для записи данных - каждому полю записи Data присвоить соответствующие данные, затем их записать в файл данных Write(DataFile,Data). Для считывания данных - Считать данные из файла Read(DataFile,Data);

•  Закрыть файл данных.

Более интересной структурой является структура сделок. :

Type {Заголовок сделки}

SdelkaInfo = record

SdelkaNumber : LongInt; {Номер сделки }

Reserved : Word;

Archive : Boolean; { Флаг архива }

ItemIndex : LongInt; {Индекс в наименованиях}

ItemsTaken : LongInt; { Всего наименований }

FirmName : String[22]; { Фирма }

Date : String[10]; {Дата выписки накладной}

OplataDate : String[10]; {Дата полной оплаты}

Summa : Real; {Сумма}

Kurs : Real; {Курс доллара}

SummaSkidka : Real; {Сумма со скидкой}

Oplata : Boolean; {TRUE - если оплачено полностью}

End;

Type

OneItemInfo = record { Наименования }

Number : LongInt;

SdelkaNumber : LongInt;

SklNum : LongInt;

Name : String[22];

Rasf : String[10];

Box : Integer;

KolVo : LongInt;

SBPrice : Real;

Price : Real;

Vozvrat : LongInt;

End;

Var

Sdelka : SdelkaInfo;

SdelkaFile : File of SdelkaInfo; { Файл SDELKA.001}

Item : OneitemInfo;

ItemsFile : File of OneItemInfo; { Файл SDELKA.002}

Структура состоит из заголовка и собственно наименований. В заголовке содержатся следующие данные : Фирма покупатель, Дата накладной, Дата оплаты, Сумма накладной в долларах США , Сумма накладной со скидкой (в рублях), Курс доллара на момент выписки накладной, Флаг архива, Количество проданных наименований, Индекс в БД с наименованиями.

В БД наименований находится информация о каждом наименовании, относящегося к соответствующей сделки.

Например, если нужно считать сделку, то надо:

•  Открыть файлы данных SdelkaFile и ItemsFile;;

•  Поместить указатель на нужную сделку в файле SdelkaFile (Seek(SdelkaFile,n));

•  Считать сделку из файла (Read(SdelkaFile,Sdelka);

•  Поместить указтель на наименование, численно равный Sdelka.ItemIndex в файл ItemsFile и для каждого наименования (от Sdelka.ItemsIndex до Sdelka.ItemsIndex+Sdelka.ItemsTaken) считывать данные. (Read(ItemsFile,Item);

•  Закрыть файлы данных SdelkaFile и ItemsFile;

На Borland Pascal это выглядит следующим образом:

OpenSdelkaFile;

OpenItemsFile; {Открытие файлов: процедуры находятся в модуле SKLFILES.PAS}

Seek(SdelkaFile,нужная сделка); {Указываю на нужную сделку}

Read(SdelkaFile,Sdelka); {и считываю ее заголовок}

for n:=Sdelka.ItemIndex to Sdelka.ItemsTaken do {Считывание инф-ции о наименованиях}

Begin

Seek(ItemsFile,n);

Read(ItemsFile,Items);

...... операции над считанными данными (вставка в коллекцию строк) .....

End;

CloseItemsFile;

CloseSdelkaFile { Закратие файлов };

Структура приходов описана также , как и структура сделок.

2.6.5. ЗАКЛЮЧЕНИЕ

Используя мощные возможности компилятора BORLAND PASCAL 7.0 и объектно-ориентированной библиотеки TURBO VISION для написания системы управления работой коммерческой компании мне удалось за очень сжатые сроки создать довольно гибкую программу с пользовательским интерфейсом очень высокого класса.