После получения таблицы-выборки, содержащей сведения по зданиям,
попавшим в запрос, сконструируем форму для работы с этой таблицей. Это будет двухстраничная форма, на первой вкладке которой –
список зданий, а на второй подробности по выбранному зданию. В окружении данных
формы (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')
ENDIF
*
Выбираем индекс для быстрого поиска
SET ORDER TO TAG ADDRESS
* Индексированный поиск здания в таблице
* SelectStreetAddress - номер улицы, на
которой стоит здание
* SelectHouseAddress - номер дома
SEEK
STR(SelectStreetAddress)+SelectHouseAddress
*
Если записей мало, можно обойтись простым поиском
* SET EXACT ON
* LOCATE
* 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')
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