4.3.5. Форма Building – форма для работы со зданиями

 

После получения таблицы-выборки, содержащей сведения по зданиям, попавшим в запрос, сконструируем форму для работы с этой таблицей. Это будет двухстраничная форма, на первой вкладке которой – список зданий, а на второй подробности по выбранному зданию. В окружении данных формы (Data Environment) разместим таблицу cBuilding и три таблицы-справочника Street (улицы), District (районы), Wall (материал стен). Для этого сделайте щелчок правой кнопки мыши в любом месте окна Form Designer. Появится меню. Выберите в нем третий пункт Data Environment. Еще один щелчок правой кнопкой, но уже в появившемся окне Data Environment активизирует очередное меню. Выберите в нем первый пункт Add. Появится окно Open. Найдите в нем таблицу cBuilding. Она находится папке WINNT\TEMP и появилась там в результате работы формы Search. Аналогичным образом добавьте в окружение данных таблицы Street, District и Wall.

Добавить объект Page Frame не сложно. Откройте панель Form Controls (элементы управления формы). Она показана на рис. 4.9. Если панель отсутствует на экране – выберите в главном меню Visual FoxPro пункт View, а в открывшемся подменю пункт Toolbars. Откроется окно Toolbars. Сделайте отметку напротив названия панели - Form Controls и щелкните кнопку OK.

Выберите на панели значок Page Frame, а в нужном месте активной области формы при помощи левой кнопки мыши отведите место для этого объекта. Форма Building с активной первой страницей и окружением данных в конструкторе форм показана на рис. 4.20.

 

 


В формах, рассмотренных ранее (Employee, Street, District, Wall) для отображения нескольких записей мы использовали List Box (поле со списком). У этого объекта один существенный недостаток - отсутствие горизонтальной линейки прокрутки. Следовательно, увидеть в списке можно лишь те колонки, которые поместились в форме. Разместим на первой странице формы альтернативу объекту List Box. Это Grid (сетка). Возможности Grid впечатляют. Вы можете установить любой ячейке сетки, связанной с таблицей,  свои индивидуальные свойства. Да и общие свойства объекта Grid отличаются большим разнообразием. Изменением этих свойств мы сможем заставить Grid заменить, да еще и на более высоком уровне объект List Box. Используем для этого Builder (построитель).

 

 

 

Рис. 4.21. Запуск построителя Grid Builder

 

 

Выберите на панели Form Controls (элементы управления формы) значок  (Grid), а в нужном месте активной области формы при помощи левой кнопки мыши отведите место для этого объекта. Для запуска построителя сделайте по объекту Grid1 щелчок правой кнопки мыши. Появится меню. Выберите в нем пятый пункт – Builder (Рис. 4.21). Откроется диалоговое окно Grid Builder. В нем четыре вкладки. Нам необходимо заполнить три из них (Grid Items, Style и Layout).

При помощи первой вкладки определяют набор полей, которые будут размещены в сетке, и последовательность их размещения. Не нажимайте клавишу Enter. Это приведет к преждевременному завершению работы построителя. Придется все начинать сначала. Вторая и третья вкладки показаны на рис. 4.22.

 


 

Вторая вкладка Style – стиль оформления. Выберите стандартный. Третья – надписи колонок и тип их содержимого. Обратите внимание на последнюю колонку Elevator (наличие лифта в здании). На рисунке она еще не имеет надписи. Если поставить в поле Control type тип Check Box, то вместо малопонятных пользователю значений .T. или .F. в колонке будет отображаться красивый значок с птичкой внутри , если лифт в здании есть.

Для завершения работы построителя сделайте щелчок по кнопке OK. Объект Grid1 появится на первой странице формы в законченном виде. Откройте окно Properties этого объекта. Нам необходимо изменить значения некоторых свойств: cделать сетку доступной только для чтения, изменить вид курсора и разрешить пользователю выделять строку только целиком. Значения этих свойств приведены в табл. 4.2.

 

Таблица 4.2

Свойства объекта Grid

 

Номер

Название свойства

Значение

1

HightLightStyle

2 – Current row highlighting enable with visual persistence

2

Mouse Pointer

1 - Arrow

3

Read Only

.T. -True

4

AllowCellSelection

.F. -False

5

RecordMark

.T. - True

 

В начале этой главы мы научилисть делать недоступными пункты меню приложения в соответствии с правилами разграничения доступа (ПРД), действующими на предприятии. Ниже приведен код, позволяющий распространить ПРД и на другие объекты приложения.

Код события Activate формы Building:

 

* Обработка прав доступа к кнопкам Печать и Квартиры

* Гашение кнопки Печать

IF WordExcel=.F.

   * Доступ к просмотру отчетов запрещен

   ThisForm.PageFrame1.Page1.Command2.Enabled=.F.

ENDIF

* Гашение кнопки Квартиры

IF WorkFlats=.F.

   * Просмотр информации по квартирам запрещен

   ThisForm.PageFrame1.Page2.Command2.Enabled=.F.

ENDIF  

 

Код события Init формы Building:

 

* Глобальные переменные для сохранения параметров адреса

* у выбранного здания. Необходимы в случае корректировки адреса

PUBLIC SelectStreetAddress,SelectHouseAddress,IndBuilding

* Номер улицы выбранного здания

SelectStreetAddress=0

* Номер дома выбранного здания

SelectHouseAddress=[]

* Признак выбора здания для просмотра

IndBuilding=0

 

Код события Destroy формы Building:

 

* Освободить глобальные переменные

RELEASE SelectStreetAddress,SelectHouseAddress,IndBuilding

 

На первой странице формы размещены три надписи. Из имена Label11, Label12 и Label13. Возьмите на вооружение методику замены заголовка надписи на реальные цифры количества зданий, попавших в запрос. Смысл этой методики вы увидите из текста события Activate.

 

Код события Activate первой страницы формы:

 

* Сброс значения признака выбора здания для просмотра

IndBuilding=0

PRIVATE CountBuilding,LandAll,CountUnder

SELECT cBuilding

* Подсчет числа зданий попавших в запрос

COUNT TO CountBuilding ALL

* Подсчет общей площади земельных участков

SUM cBuilding.Land TO LandAll

* Подсчет общей площади нежилых помещений

SUM cBuilding.Square TO CountUnder

* Отображение данных по выборке на первой странице формы

ThisForm.PageFrame1.Page1.Label11.Caption=;

    [В запрос попало зданий  ]+;

    ALLTRIM(STR(CountBuilding,4))+[ шт.]

ThisForm.PageFrame1.Page1.Label12.Caption=;

    [Общая площадь участков ]+ALLTRIM(STR(LandAll,13,1))+[ кв.м.]

ThisForm.PageFrame1.Page1.Label13.Caption=;

    [Площадь нежилых помещений ]+;

    ALLTRIM(STR(CountUnder,13,1))+[ кв.м.]

* Перерисовать первую страницу формы

ThisForm.PageFrame1.Page1.Refresh

 

Код события Init сетки Grid1:

 

* Выполнить раскрашивание строк Сетки через одну

* Цвет фона

THISFORM.PageFrame1.Page1.grid1.SETALL("dynamicBackColor",;

  "IIF(MOD(RECNO( ), 2)=0, RGB(255,255,255), RGB(234,234,234))";

  , "Column")

* Цвет текста

THISFORM.PageFrame1.Page1.grid1.SETALL("dynamicForeColor",;

  "IIF(MOD(RECNO( ), 2)=0, RGB(0,0,0), RGB(255,0,0))", "Column")

 

Код события DblClick сетки Grid1:

 

* Здание для просмотра выбрано

IndBuilding=1

* Сделать активной вторую страницу

ThisForm.PageFrame1.ActivePage=2

 

Код события Click сетки Grid1:

 

* Здание для просмотра выбрано

IndBuilding=1

 

Код события Activate второй страницы формы:

 

* Выбрано ли здание для просмотра?

IF IndBuilding=0         

     * Выбор не сделан

     =MESSAGEBOX('Ни одно здание не выбрано! ',;

                48,' Внимание!')

     * Вернуться на первую страницу формы

     THISFORM.PAGEFRAME1.ACTIVEPAGE=1

ENDIF

* Номер улицы выбранного здания

SelectStreetAddress=cBuilding.Street

* Номер дома выбранного здания

SelectHouseAddress=cBuilding.House

* Делаем недоступной кнопку "Записать"

ThisForm.PageFrame1.page2.Command4.Enabled=.F.    

* Делаем недоступным Класс Building1

ThisForm.PageFrame1.page2.Building1.Enabled=.F.

* Определение местоположения фотографии здания

SET EXACT ON

IF ALLTRIM(SYS(2003))=[\]

   RealDirectory=[]

ELSE

   RealDirectory=[\]

ENDIF     

SET EXACT OFF

* Есть фотография - значение переменной FileName

FileName=DISK+RealDirectory+[Picture\]+;

ALLTRIM(cBuilding.Picture)+[.jpg]

* Нет фотографии - значение переменной NoFileName

NoFileName=DISK+RealDirectory+[Picture\]+[NoFoto.jpg]

IF FILE(FileName)

   * Если фотография имеется в папке Picture

   * Разместить ее на месте картинки IMAGE1

   THIS.IMAGE1.PICTURE=FileName

ELSE

   * Если нет - взять картинку NoFoto.jpg

   THIS.IMAGE1.PICTURE=NoFileName

ENDIF  

* Перерисовать страницу формы

THIS.Refresh

 

Вторая страница формы Building (рис. 4.23) содержит информацию по выбранному для просмотра зданию. Основное место отведено под класс Building1.  На рисунке он выделен. Этот же визуальный класс используется также в форме AddBuild (Занесение нового здания).

 


 

Обратите внимание на событие, которое наступит при потере фокуса объектом txtPicture класса Building1. Немедленно после занесения имени файла, содержащего фотографию здания, его изображение появится на месте объекта Image1.

 

Код события LostFocus объекта txtPicture класса Building1:

 

* Определение местоположения фотографии здания

SET EXACT ON

IF ALLTRIM(SYS(2003))=[\]

   RealDirectory=[]

ELSE

   RealDirectory=[\]

ENDIF     

SET EXACT OFF

* Есть фотография - значение переменной FileName

FileName=DISK+RealDirectory+[Picture\]+;

ALLTRIM(cBuilding.Picture)+[.jpg]

* Нет фотографии - значение переменной NoFileName

NoFileName=DISK+RealDirectory+[Picture\]+[NoFoto.jpg]

IF FILE(FileName)

   * Если фотография имеется в папке Picture

   * Разместить ее на месте картинки IMAGE1

   THISFORM.PAGEFRAME1.PAGE2.IMAGE1.PICTURE=FileName

ELSE

   * Если нет - взять картинку NoFoto.jpg

   THISFORM.PAGEFRAME1.PAGE2.IMAGE1.PICTURE=NoFileName

ENDIF  

 

Если пользователь сделает щелчок левой кнопкой мыши по фотографии здания, то сработает код события Click объекта Image1. Этот код создавался на протяжении десяти лет, пополняясь с появлением новых операционных систем. Одни стандартные просмотрщики изображений заменялись на другие, только один Paint оставался неизменным. Именно на нем я и остановил свой выбор. Будем надеяться, что Windows Vista, которую Microsoft обещает выпустить в 2007 году, не расстанется с Paint и код будет работать.

Код события Click объекта Image1:

 

IF LEN(ALLTRIM(cBuilding.Picture))=0

    =MESSAGEBOX('В архиве отсутствует фото этого здания',;

          48,' Внимание')

    RETURN

ENDIF

SET EXACT ON

IF ALLTRIM(SYS(2003))=[\]

   RealDirectory=[]

ELSE

   RealDirectory=[\]

ENDIF     

SET EXACT OFF

FileName1=DISK+RealDirectory+[PICTURE\]+;

ALLTRIM(cBuilding.Picture)+[.jpg]

* Поиск просмотрщика картинок

FileVeiwver=[ ]

* WINDOWS 95

IF FILE ('C:\WINDOWS\WANGIMG.EXE')

   FileVeiwver='C:\WINDOWS\WANGIMG.EXE '

ENDIF  

* WINDOWS 98

IF FILE ('C:\WINDOWS\KODAKIMG.EXE')

   FileVeiwver='C:\WINDOWS\KODAKIMG.EXE '

ENDIF  

* WINDOWS NT 4.0 WorkStation

IF FILE ('C:\Program Files\Windows NT\Accessories\ImageVue\wangimg.exe')

   FileVeiwver='C:\Program Files\Windows NT\Accessories\ImageVue\wangimg.exe'

ENDIF

* WINDOWS 2000

IF FILE ('C:\Program Files\Windows NT\Accessories\ImageVue\kodakimg.exe')

   FileVeiwver='C:\Program Files\Windows NT\Accessories\ImageVue\kodakimg.exe'

ENDIF

* WINDOWS XP и другие ОС Выбираем PAINT

IF FILE ('C:\Windows\System32\Mspaint.exe')

   FileVeiwver='C:\Windows\System32\Mspaint.exe'

ENDIF

IF FileVeiwver=[ ]

    =MESSAGEBOX('На Вашем компьютере отсутствует’+;

     ‘ просмотрщик изображений!',48,' Внимание')

    RETURN

ENDIF

IF FILE('&FileName1')

   * Запуск просмотрщика изображений

   RUN /N1 &FileVeiwver &FileName1

ELSE

      =MESSAGEBOX('Пропал файл с изображением этого здания!',;

          48,' Внимание')

ENDIF  

         

Код события Click кнопки Исправить:

 

*- Кнопка Исправить

* Первую страницу делаем недоступной

ThisForm.PageFrame1.page1.Enabled=.F.             

* Меняем заголовок второй страницы "Просмотр" на "Корректировка"

ThisForm.PageFrame1.page2.Caption=[Корректировка] 

* Делаем доступной кнопку "Записать"

ThisForm.PageFrame1.page2.Command4.Enabled=.T.    

* Делаем недоступной кнопку "Удалить"

ThisForm.PageFrame1.page2.Command1.Enabled=.F.    

* Делаем недоступной кнопку "Квартиры"

ThisForm.PageFrame1.page2.Command2.Enabled=.F.    

* Меняем заголовок кнопки "Выход" на "Отказ"

ThisForm.PageFrame1.page2.Command3.Caption=[Отказ]

* Делаем доступным Класс Building1

ThisForm.PageFrame1.page2.Building1.Enabled=.T.

Код события Click кнопки Записать:

 

*- Кнопка Записать

lnMsgResult=MESSAGEBOX('Сейчас результаты корректировки '+;

               'будут записаны на диск.',52,'Подтвердите!')

IF lnMsgResult=6  

   SELECT cBuilding

   SCATTER MEMO MEMVAR

  * Корректировка в основной базе

  IF .NOT. USED ('Building')

     USE Building IN 0

  ENDIF

  SELECT Building

  * Выбираем индекс для быстрого поиска

  SET ORDER TO TAG ADDRESS

  * Индексированный поиск здания в таблице

  * SelectStreetAddress - номер улицы, на которой стоит здание

  * SelectHouseAddress - номер дома

  SEEK STR(SelectStreetAddress)+SelectHouseAddress

  * Если записей мало, можно обойтись простым поиском

  *  SET EXACT ON

  *  LOCATE FOR Street=cBuilding.Street AND House=cBuilding.House

  *  SET EXACT OFF

  IF FOUND()

     GATHER MEMO MEMVAR

  ELSE

     =MESSAGEBOX('Нет доступа к таблице зданий '+;

       ' или в таблице отсутствует здание, данные которого '+;

       'Вы редактировали.',48,'А вот Вам и проблема!')

  ENDIF

  THISFORM.Release

ENDIF

 

Код события Click кнопки Удалить:

 

lnMsgResult=MESSAGEBOX('Подтвердите!',52,'Удаление!')

IF lnMsgResult=6  

  * Удаление в основной базе

  IF .NOT. USED ('Building')

     USE Building IN 0

  ENDIF

  SELECT Building

  * Выбираем индекс для быстрого поиска

  SET ORDER TO TAG ADDRESS

  * Индексированный поиск здания в таблице зданий

  * SelectStreetAddress - номер улицы, на которой стоит здание

  * SelectHouseAddress - номер дома

  SEEK STR(SelectStreetAddress)+SelectHouseAddress

  IF FOUND()

     * Если здание найдено - удалить его

     DELETE

  ENDIF

  THISFORM.Release

ENDIF

 

Код события Click кнопки Квартиры:

 

*- Кнопка Квартиры

* Выборка всех квартир дома в C:\WINNT\TEMP\cFlat.dbf

SELECT Flat.Street,Flat.House,;

       Flat.Flat,Flat.Storey,Flat.rooms,;

       Flat.SquareFlat,Flat.Dwell,Flat.Branch,;

       Flat.Balcony,Flat.Height,Flat.Account;

         FROM Flat;

         WHERE Flat.Street=SelectStreetAddress;

              AND Flat.House==SelectHouseAddress;

         INTO TABLE 'C:\WINNT\TEMP\cFlat.dbf';

         ORDER BY Flat

* Запуск формы для работы с квартирами

DO FORM Flat