Пример создания информационно-справочной системы
в среде Visual Prolog.
Информационно-справочная система
«Литература»
Разработка к.т.н. Николаенко Н.Н.
Цель данной работы – помочь учащимся в разработке простых приложений в среде Visual Prolog (ver. 5.2). В рассмотренном примере демонстрируется применение стандартных диалогов, диалогов созданных пользователем и других средств визуальной среды Visual Prolog. При реализации примера опущены вопросы, связанные с целостностью баз данных, оптимизацией диалогов и кодов программы. Предлагается учащемуся самостоятельно решить подобные вопросы.
Задание
Создать информационно-справочную систему «Литература», которая должна обеспечивать:
- хранение следующей информации по книгам: автор(ы), название книги, вид переплета (мягкий, твердый), категорию книги (бизнес, наука, художественная и др.), наличие электронного диска (есть или нет), вид обложки книги (файл типа bmp);
- просмотр, редактирование, удаление информацию по книгам, и категориям;
- выводить в окно сообщений и в файл карточку выбранной книги;
- устанавливать по умолчанию шрифт в окне сообщений.
Описание работы системы
После запуска системы открывается основное окно (Task):
|
Рис.1 |
здесь к пунктам меню, которые система создает по умолчанию, добавлены пункты База и Категории и Настройки с подпунктами (рис. 2 и 3 соответственно). Пункты меню Файл и Help в разрабатываемой системе не используются.
При выборе пункта Ввод Данных открывается диалог, показанный на рис.4. Оператор вводит необходимые данные. После нажатия кнопки ВидОбл открывается стандартный диалог для выбора файла обложки. После выбора файла, вид обложки появляется в верхней правой части основного окна и в поле Файл диалога Ввод данных заносится имя файла обложки. Окно с обложкой закрывается при нажатии кнопок ОблЗакрыть или Cancel и при закрытии окно диалога. При повторном открытии файла с обложкой появляется стандартный диалог (рис. 6). При нажатии кнопки Нет появляется файл ранее выбранной обложкой, иначе появляется диалог для выбора нового файла обложки.
При нажатии кнопки ОК выполняется запись введенных данных в базу и на экране кратковременно (на 1 секунду) появляется диалоговое окно с информацией о записи данных (рис. 7). При попытке ввода существующих данных выводится стандартный диалог с информацией об ошибке (рис. 8).
Рис.5 |
При выборе пункта меню Удал/Редакт/Вывод открывается окно со списком литературы, которая хранится в базе (рис. 9). Каждая запись списка представлена кодом, и далее значениями реквизитов базы описанных в задании. Окно имеет меню с пунктами Удалить, Редактировать, Вывести карточку, Window и панель инструментов с соответствующими пиктограммами. Первые 3 пункта меню и пиктограммы пассивны и открываются при выборе элемента из списка.
При выборе пункта Удалить производится запрос на подтверждение операции и после подтверждения запись удаляется из базы данных.
В случае выбора пункта Редактировать открывается диалог (рис. 4) и можно выполнить редактирование выбранной записи. При выборе пункта Вывести карточку открывается окно (если оно было закрыто) и в него выводится карточка выбранной записи (рис. 10). Одновременно производится запись карточки в файл. Шрифт текста выводимого в окно сообщений можно предварительно установить через меню Настройки главного меню. При выборе этого пункта вызывается стандартный диалог выбора шрифта.
Структура программы
Для реализации программы помимо основного файла проекта используются файлы:
ОписаниеРабБаз. pro – здесь описываются все рабочие базы и константы;
Библиотека.pro – для хранения универсальных процедур (работа со списками, циклами и др.);
ПроцПользователя. pro –здесь размещаются все процедуры созданные пользователем для данного примера (инструментальные процедуры).
Реализация системы
1.
Создание процедур
по работе с Категориями.
Для хранения категорий литературы будем использовать справочник, который представляет собой динамическую базу данных, хранящуюся на диске. Используем для работы со справочником стандартные диалоги (Common Dialog), которые позволят вводить новые данные, редактировать, удалять и просматривать данные справочников.
1.1. Создадим пункты меню для работы с категориями литературы (см. лаб.раб.№6):
1.2. Создадим проект и проверим полученное меню.
В дальнейшем рекомендуем проверять внесенные в проект изменения путем создания запуска проекта в работу..
1.3. Создадим в каталоге EXE проекта файл с пустой именованной базой для хранения Категорий литературы (см. лаб.раб.№7).
Структура базы:
%Описание базы Категорий литературы
facts - Катег_лит
категории_лит(string
КатегорияЛит)
/************Описание баз
данных**************/
constants
%Имя базы данных Категорий
литературы
имяБазыКатегЛит="КатегЛитер.pbs"
%Описание базы Категорий литературы
facts - Катег_лит
категории_лит(string
КатегорияЛит)
/************Процедура загрузки
баз данных ***************/
predicates
загрузить_раб_Базы
clauses
загрузить_раб_Базы:-
consult(имяБазыКатегЛит,Катег_лит).
1.6. Подключим к файлу ИМЯ_ПРОЕКТА.pro файлы описания и загрузки баз данных.
/*******************************************************************
Copyright
(c) ИТ
Project: ПРИМЕРСПРЛИТЕРАТУРА_0
FileName: ПРИМЕРСПРЛИТЕРАТУРА_0.PRO
Purpose: No description
Written by: Visual Prolog
Comments:
********************************************************************/
include "примерспрлитература_0.inc"
include "примерспрлитература_0.con"
include
"hlptopic.con"
include "ОписаниеРабБаз.pro"
include "ПроцПользователя.pro"
%BEGIN_WIN Task Window
Здесь и в дальнейшем жирным шрифтом в коде программы выделен добавленный пользователем при выполнении пункта код. Обычным шрифтом указан код, который генерируется экспертом кода автоматически либо ранее был введен пользователем.
1.7. Добавим в файле ИМЯ_ПРОЕКТА.pro вызов процедуры загрузки баз данных с категориями литературы.
%BEGIN Task Window,
e_Create
task_win_eh(_Win,e_Create(_),0):-!,
%BEGIN Task Window,
InitControls, 10:41:46-26.5.2014, Code automatically updated!
%END Task Window,
InitControls
%BEGIN Task Window,
ToolbarCreate, 10:41:46-26.5.2014, Code automatically updated!
tb_project_toolbar_Create(_Win),
tb_help_line_Create(_Win),
%END Task Window,
ToolbarCreate
% загрузим базы с видами и категориями
загрузить_раб_Базы,
ifdef use_message
msg_Create(100),
enddef
!.
1.8. Создадим файл Библиотека.pro и добавим в него процедуры сортировки списка и проверки вхождения элемента в список.
Эти процедуры будут использоваться при работе с категориями. После создания процедур рекомендуем проверить процедуры в режиме TestGoal (см. лаб.раб. №5). В дальнейшем рекомендуем проверять в этом режиме все созданные процедуры, которые не «завязаны» на визуальную среду.
%+Сортировка списка по возрастанию
PREDICATES
sort(slist ИсходныйСписок,slist ОтсортированныйСписок)
nondeterm perest(slist ВхСписок,slist СписокПослеПерестановки
)
Clauses
sort(L,Ls):-
perest(L,L1),!,
sort(L1,Ls).
sort(Ls,Ls).
perest([X,Y|Tail],[Y,X|Tail]):- X>Y.
perest([Z|Tail],[Z|Tail1]):-
perest(Tail,Tail1).
%-
%+Процедура вхождения Элемента в список
PREDICATES
входитВСписок(string
Элемент,slist Список)
clauses
входитВСписок(Элемент,[Элемент|
_]):-!.
входитВСписок(Элемент,[_|Остаток]):-
входитВСписок(Элемент,Остаток).
%-
1.9. Подключим к файлу ИМЯ_ПРОЕКТА.pro файл Библиотека.pro.
/*******************************************************************
Copyright
(c) ИТ
Project: ПРИМЕРСПРЛИТЕРАТУРА_0
FileName: ПРИМЕРСПРЛИТЕРАТУРА_0.PRO
Purpose: No description
Written by: Visual Prolog
Comments:
********************************************************************/
include "примерспрлитература_0.inc"
include "примерспрлитература_0.con"
include
"hlptopic.con"
include "ОписаниеРабБаз.pro"
include "Библиотека.pro"
%BEGIN_WIN Task Window
1.10. Создадим обработчик события выбора пункта меню Ввод категории.
Порядок создания обработчика события описан лаб.раб.№6.
%BEGIN Task Window,
id_Операции_Категория_ввести
task_win_eh(_Win,e_Menu(id_Операции_Категория_ввести,_ShiftCtlAlt),0):-!,
!.
%END Task Window,
id_Операции_Категория_ввести
1.11. Добавим в обработчик события код, обеспечивающий ввод новой категории.
%BEGIN Task Window, id_Операции_Категория_ввести
task_win_eh(_Win,e_Menu(id_Операции_Категория_ввести,_ShiftCtlAlt),0):-!,
%+Введем категорию с помощью
стандартного диалога
Msg="Введите\n
новую\n категорию литературы",
InitStr="",
Title="Ввод
категории литературы",
_NewSTRING=dlg_GetStr(Title,Msg,InitStr),
%-
_NewSTRING<>"",
%Категория введена. Проверим на повтор..
%Получим список Существующих
категорий
findall(Категория,категории_лит(
Категория), СписокКатегорий ),
%Проверим есть ли новая
категория в этом списке
not(входитВСписок(_NewSTRING,
СписокКатегорий)),
%Занесем в базу новую
категорию
assert(категории_лит(
_NewSTRING),Катег_лит),
%Запишем базу категорий на
диск
save(имяБазыКатегЛит,Катег_лит),
!.
%END Task Window, id_Операции_Категория_ввести
Здесь код обработки события добавлен непосредственно в обработчик. Последнее сделано для исключения лишних ссылок, но мы рекомендуем писать отдельные процедуры обработки события и размещать их в отдельном файле, а в обработчиках событий делать вызов этих процедур.
1.12. Создадим обработчик события выбора пункта меню Редактировать категорию и добавим код, обеспечивающий редактирование выбранной категории.
1.12.1. Создадим в файле Библиотека.pro процедуру получения сортированного списка категорий. Эта процедура повысит удобство при выборе из списка нужной категории.
%+Процедура получение сортированного списка
Категорий
PREDICATES
получитьСортировСписокКатегорий(slist
Список)
clauses
получитьСортировСписокКатегорий(Список):-
%Получим список Существующих
категорий
findall(КатегорияЛит,категории_лит(КатегорияЛит),
СписокКатегорияЛит ),
%Сортируем список
Существующих категорий
sort(СписокКатегорияЛит,Список).
%-
1.12.2. Создадим обработчик события выбора пункта меню Редактировать категорию.
%BEGIN Task Window,
id_Операции_Категория_редактировать
task_win_eh(_Win,e_Menu(id_Операции_Категория_редактировать,_ShiftCtlAlt),0):-!,
!.
%END Task Window,
id_Операции_Категория_редактировать
1.12.3. Создадим код обработчика события выбора пункта меню Редактировать категорию.
%BEGIN Task Window, id_Операции_Категория_редактировать
task_win_eh(_Win,e_Menu(id_Операции_Категория_редактировать,_ShiftCtlAlt),0):-!,
выбратьКатегорию("Выбор категории для редактирование",, StrSel),
%Отредактируем в диалоге
выделенную категорию
Msg="Отредактируйте
выделенную строку",
InitStr=_StrSel,
TitleР="Редактирование",
_NewSTRING=dlg_GetStr(TitleР,Msg,InitStr),
%Если категория была
изменена, запросим сохранение
_NewSTRING<>InitStr,
concat("Сохранить\nкатегорию'\n",_
NewSTRING,Вопрос),
ANSWER
= dlg_Ask(_Win,"Редактирование",Вопрос,["&Да","&Нет"]),
%Сохраним, если ответили ДА
ANSWER=0,
%ввели ДА (0)
retract(категории_лит(InitStr),Катег_лит),
assert(категории_лит(_NewSTRING),Катег_лит),
save(имяБазыКатегЛит,Катег_лит),
!.
%END Task Window, id_Операции_Категория_редактировать
Здесь подготовка сортированного списка категории и выбор категории из него делается инструментальной процедурой:
predicates
выбратьКатегорию(string ЗаголовокОкнаДиалога, string ВыбраннаяКатегория)
clauses
выбратьКатегорию(Title, _StrSel):-
получитьСортировСписокКатегорий(СписокКатегорий),
%Выберем в диалоге из этого списка редактируемую
категорию _StrSel
SLIST=СписокКатегорий,
PreSel=0, %По
умолчанию выделим в диалоге первый элемент списка
Ответ=dlg_ListSelect(Title,SLIST,PreSel,_StrSel,_Index),
Ответ=b_True.
В ней выбор категории для редактирования делается с использованием стандартного диалога dlg_ListSelect(….).
Для подтверждения сохранения новой категории в обработчике события был применен стандартный диалог dlg_Ask(…).
1.13. Создадим обработчик события выбора пункта меню Удалить категорию и добавим код, обеспечивающий удаление выбранной категории.
Ниже приведен созданный обработчик и код программы обработки этого события.
%BEGIN Task Window, id_Операции_Категория_удалить
task_win_eh(_Win,e_Menu(id_Операции_Категория_удалить,_ShiftCtlAlt),0):-!,
выбратьКатегорию("Удаление
категории литературы",_StrSel),
%Запросим подтверждение
concat("Удалить\nкатегорию\n",_StrSel,Вопрос),
ANSWER = dlg_Ask(_Win,"Удаление",Вопрос,["&Да","&Нет"]),
%Удалим, если подтвердили
ANSWER=0,
%ввели ДА
retract(категории_лит(_StrSel),Катег_лит),
%Сохраним обновленную базу
категорий
save(имяБазыКатегЛит,Катег_лит),
!.
%END Task Window, id_Операции_Категория_удалить
1.14. Создадим, обработчик события выбора пункта меню Просмотр Категорий и добавим код, обеспечивающий удаление выбранной категории.
%BEGIN Task Window, id_Операции_Категория_просмотр
task_win_eh(_Win,e_Menu(id_Операции_Категория_просмотр,_ShiftCtlAlt),0):-!,
выбратьКатегорию("Просмотр
списка категорий",_StrSel),
!.
%END Task Window, id_Операции_Категория_просмотр
2.
Создание процедур
для работы с базой данных литературы.
2.1. Создадим меню База с пунктами подменю Ввод данных, Удал/Редакт/Вывод (рис. 2).
2.2. Создадим диалог для ввода данных (рис. 4).
Диалог создается через окно проекта. Порядок создания схематично показан ниже.
После нажатия ОК появится редактор Диалога:
Используя элементы Controls, создадим диалог для ввода данных по литературе:
При создании элемента задайте константы, которые будут идентифицировать элемент диалога в системе. Если необходимо, то установите флаги элемента управления. Для элементов редактирования константа формируется автоматически после ввода текста в поле Text. На рис. 14 показано построение элемента диалога для ввода автора книги.
В табл. 1 показаны константы и флаги, которые нужно установить для элементов диалога Ввод данных (остальные принять по умолчанию):
Назначение элемента |
Имя константы |
Установленные флаги |
Ввод автора |
idc_автор |
|
Ввод наименование книги |
idc_наименование |
|
Выбор категории |
категория |
|
Независимый переключатель наличия электронного диска |
idc_диск |
|
Зависимый Переключатель выбора твердого переплета |
idc_твердый |
|
Зависимый Переключатель выбора мягкого переплета |
idc_мягкий |
|
Поле для отображения имени файла обложки |
idc_обложка |
Desabled |
Кнопка отображения вида обложки |
idc_видобл |
|
Кнопка закрытия окна с видом обложки |
idc_облзакрыть |
Desabled |
После закрытия диалога подтвердите сохранение введенных параметров.
2.2.1. Создадим в модуле проекта программный код для создания диалога ввода данных.
Вызовите эксперта кода Dialog and Window (рис.15), выберите диалог Ввод данных, модуль где будет располагаться созданный экспертом код (ИМЯ_ПРОЕКТА.pro), стиль кода dialog_Create() и нажмете кнопку Default Code. Будет автоматически сформирован код по созданию диалога ввода данных.
2.2.2. Создадим процедуру обработки события пункта меню «Ввод данных».
Порядок создания описан в п. 1.10.
%BEGIN Task Window, id_База_ввод_данных
task_win_eh(_Win,e_Menu(id_База_ввод_данных,_ShiftCtlAlt),0):-!,
!.
%END Task Window, id_База_ввод_данных
2.2.3. Добавьте через контекстное меню в текст обработчика этого события код, который создаст на экране диалог.
Вставка кода делается через контекстное меню. Предварительно маркер мыши нужно установить между знаками отсечения (!) обработчика события выбора пункта меню Ввод данных. Последовательность вставки и сам код показаны на рис. 16 . Диалог Insert Call… можно вызвать также командой Ctrl-Shift-W.
Результат вставки:
%BEGIN Task Window, id_База_ввод_данных
task_win_eh(_Win,e_Menu(id_База_ввод_данных,_ShiftCtlAlt),0):-!,
dlg_ввод_данных_Create(_Win),
!.
%END Task Window, id_База_ввод_данных
2.3. Определим начальные значения, которые будут отображать элементы диалог и «поведение» элементов диалога.
2.3.1. Запустим через эксперт диалога и окна пакет Dialog Pack. (Окно проекта кнопка Dialog-CodeExpert-DialogPack).
Экран эксперта диалогового пакета можно условно разделить на две части (рис. 17). Левая область всегда содержит список доступных элементов диалога (управления). Некоторые из них снабжены префиксом + (плюс): двойной щелчок на + отображает детальную информацию. Правая часть имеет несколько полей, которые используются для отображения и изменения различных настроек выбранного элемента управления в левой части элемента диалога. На рис. 17 в его левой части показан список детальной информации элемента диалога Категория и выделенного элемента RB Groups (группы радиокнопок), а в правой сделанные установки для радио кнопок выбора переплета. Для этих кнопок создана группа с идентификатором idc_твердый, из поля «Available RB» в «RB in Group» перенесены идентификаторы кнопок вошедших в группу и задана переменная ПЕРЕПЛЕТ, которая позволит устанавливать и читать состояние переключателя.
Далее из левого списка по очереди следует выбрать необходимые элементы диалога и выполнить установки (задать переменные, установить начальные значения). В табл. 2 показаны сделанные установки.
Элемент управления |
Variable type |
Setting method |
Item number |
Variable (itemlist) |
initiate as |
Автор |
String |
Variable |
- |
АВТОР |
"" |
Наименование |
String |
Variable |
- |
НАИМЕНОВАНИЕ |
"" |
Диск |
- |
Variable |
- |
ДИСК |
b_false |
Выбор категории |
- |
Variable |
0 |
КАТЕГОРИЯ |
- |
Обложка |
String |
Variable |
- |
ОБЛОЖКА |
"" |
2.3.2. Создадим обработчик события создания диалога ввода данных (е_Create).
%BEGIN Ввод данных, e_Create
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-!,
!.
%END Ввод данных, e_Create
2.3.3. Создадим программный код обработки события е_Create.
Перейдем в режим редактирования обработчика и добавим в него код установки в начальное состояние списка категорий литературы:
%BEGIN Ввод данных, e_Create
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-!,
%Установим
значения элементов диалога
%Загрузим список категорий
findall(КатегорияЛит,категории_лит(КатегорияЛит),ListКатегорияЛит
),
sort(ListКатегорияЛит,ListКатегорияЛит1),
ID_Категория=win_GetCtlHandle(_Win,категория),
lbox_Add(ID_Категория, 0,
ListКатегорияЛит1),
%Покажем в списке элем.диалога первый элемент
lbox_SetSel(ID_Категория,0,b_True),
%Установим фокус на поле
Автор
ID_Автор=win_GetCtlHandle(_Win,idc_автор),
win_SetFocus(ID_Автор),
!.
%END Ввод данных, e_Create
2.4. Создадим описание основной базы для хранения литературы процедуры ее загрузки.
Откроем файл ОписаниеРабБаз.pro и добавим в конец его код описания и загрузки базы как это сделано в пп.1.4 и 1.5. Отметим, что в базы добавлен рабочий реквизит Код. Он идентифицирует запись базы данных.
/********Описание основной
базы**************************/
constants
имяБазыЛит="Литература.pbs"
%Описание базы литературы
facts - Литература
база_лит(
integer
Код, %Код
записи, число от 1-... Формируется программно
string
Автор,
string
Наименование,
string
Категория, %Категория, выбранная из
базы категорий
integer
Диск, %0 - диска нет, 1- есть
integer
Переплет, %0 -
Переплет мягкий , 1-твердый
string
Обложка) %Имя файл без пути образа
обложки (тип .bmp) /************Процедура загрузки основной базы данных *****/
predicates
загрузить_Основную_Базу
clauses
загрузить_Основную_Базу:-
consult(имяБазыЛит,Литература).
2.4.1. Создадим файл с пустой базой литературы (см.п.0).
2.4.2. Добавим в основной файл проекта загрузку описанной базы.
%BEGIN Task Window,
e_Create
task_win_eh(_Win,e_Create(_),0):-!,
%BEGIN Task Window,
InitControls, 10:41:46-26.5.2014, Code automatically updated!
%END Task Window,
InitControls
%BEGIN Task Window,
ToolbarCreate, 10:41:46-26.5.2014, Code automatically updated!
tb_project_toolbar_Create(_Win),
tb_help_line_Create(_Win),
%END Task Window,
ToolbarCreate
% загрузим базы с видами и категориями
загрузить_раб_Базы,
% загрузим основную базу
загрузить_Основную_Базу,
ifdef use_message
msg_Create(100),
enddef
!.
%END Task Window,
e_Create
2.4.3. Создадим обработчик события нажатия кнопки ОК (см.п.Ошибка! Источник ссылки не найден.).
%BEGIN Ввод данных, idc_ok
_CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_ok,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
!.
%END Ввод данных, idc_ok _CtlInfo
2.5. Создадим код обработки события «нажатие кнопки ОК». При нажатии ОК выполняется запись в базу данных, если в базе нет таких данных, иначе выводится сообщения, что эти данные есть.
Перейдем в режим редактирования обработчика и добавим в него код
записи введенных данных в основную базу и сохранения ее на диске.
%BEGIN Ввод данных, idc_ok _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_ok,_CtrlType,_CtrlWin,_CtlInfo),0):-
%!,
%Прочитаем состояние элементов диалога
прочитаемТекстЭлДиалога(_Win,idc_автор,_Автор),
прочитаемТекстЭлДиалога(_Win,idc_наименование,_Наименование),
прочитаемТекстЭлДиалога(_Win,категория,_Категория),
прочитаемТекстЭлДиалога(_Win,idc_обложка,_Обложка),
прочитаемСостояниеЭлДиалога(_Win,idc_диск,_Диск),
прочитаемСостояниеЭлДиалога(_Win,idc_твердый,_Переплет),
%Запишем новые данные, если их нет в базе
%Сформирует список кодов, если он пустой, то такой
записи нет
findall(Коды,база_лит(Коды,_Автор,_Наименование,_Категория,_Диск,_Переплет,_Обложка),СписокКодовОдинаковыхСтрок),
%В базе есть такая запись?
в_базеНетТакойЗаписи(СписокКодовОдинаковыхСтрок),
%СписокКодовОдинаковыхСтрок=[],
%Да, Прочитаем данные о выделенном в окне
списка элементе списка
формирумНовыйКод( КодНовый),
%Запишем новые данные
asserta(база_лит(КодНовый,_Автор,_Наименование,_Категория,_Диск,_Переплет,_Обложка),Литература),
save(имяБазыЛит,Литература),
win_Destroy(_Win),
!.
dlg_ввод_данных_eh(_Win,e_Control(idc_ok,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
!.
%END Ввод данных, idc_ok _CtlInfo
Ниже идут тексты инструментальных процедур:
predicates
прочитаемСостояниеЭлДиалога(window
ОкноДиалога,integer Id,integer Состояние)
прочитаемТекстЭлДиалога(window
ОкноДиалога,integer Id, string Текст)
clauses
прочитаемСостояниеЭлДиалога(Win,Id,Состояние):-
ID_Элемента=win_GetCtlHandle(Win,Id),
Состояние=win_IsChecked(ID_Элемента).
прочитаемТекстЭлДиалога(Win,Id,Текст):-
ID_Элемента=win_GetCtlHandle(Win,Id),
Текст=win_GetText(ID_Элемента).
Predicates
%Выведет сообщение, если
список кодов записей не пуст
в_базеНетТакойЗаписи(ilist
СписокКодов)
clauses
в_базеНетТакойЗаписи([]):-!.
в_базеНетТакойЗаписи(_):-
_Answer
= dlg_MessageBox( "Информация", "В базе уже\nесть такая
запись!", mesbox_iconInformation,
mesbox_buttonsOK,
mesbox_defaultfirst, mesbox_suspendapplication ),
fail.
Predicates
%Формирует код от 1 до мах+1. Использует базу
списокКодов() рабочей области
nondeterm формирумНовыйКод(integer НовыйКод)
clauses
формирумНовыйКод(1):-
findall(Код,база_лит(Код,_,_,_,_,_,_),ListКодов),
assert(списокКодов(ListКодов),Рабочая),
ListКодов=[],
!.
формирумНовыйКод(Код):-
списокКодов(СписокКодов),
максЭлСписка(СписокКодов,
МаксЭлем),
Код=МаксЭлем+1.
Описание базы списокКодов() сделано в
области Рабочая в файле ОписаниеРабБаз.pro и имеет вид.
facts - Рабочая
single списокКодов(ilist)%Хранит список кодов базы Литература
clauses
%Установим
начальные значения
списокКодов([0]).
Процедуру максЭлСписка разместим в файле Библиотека.pro
%Находит мак элемент в списке
predicates
nondeterm максЭлСписка(ilist Список, integer МаксЭлем)
clauses
максЭлСписка([Элемент],
Элемент).
максЭлСписка([Элемент|Хвост],
Элемент):-
максЭлСписка(Хвост,
МакЭлемХвоста),Элемент>МакЭлемХвоста,!.
максЭлСписка([_|Хвост],
МакЭлемент):-максЭлСписка(Хвост, МакЭлемент).
2.6. Создадим обработчик события нажатия кнопки ОблОткрыть диалога «Ввод данных» (рис. 13).
При нажатии кнопки открывается диалог, в котором нужно выбрать файл Обложки. Его имя (без пути к файлу) выводится в поле Обложка. Если имя уже есть то, при нажатии кнопку делается запрос о возможном выборе нового файла, иначе выводится вид старой обложки.
2.6.1. Создадим окно для просмотра обложки.
В этом окне в дальнейшем будем отображать рисунок обложки. При создании окно будет пустым. Перейдем на панель проекта и выберем Window-New. Выберем в окне проекта Windows-New. Появится диалог атрибутов окна: введем имя Обложка, при необходимости можно установить координаты левого верхнего угла окна (X,Y), ширину и высоту окна. В нашем случае эти параметры рассчитываются программно (п. 2.6.8). Нажмем ОК. Сохраним параметры окна.
Рис.18 |
2.6.2. Вызовем Эксперт кода для созданного окна (рис. 19), выберем модуль где будет размещаться программа работы с окном и нажав DefaultCode создадим в этом модуле процедуру создания окна win_Create(…).
2.6.3. Добавим обработчик события нажатия кнопки ОблОткрыть диалога Ввод данных (рис. 13).
%BEGIN Ввод данных,
idc_видобл _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_видобл,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
!.
%END Ввод данных,
idc_видобл _CtlInfo
2.6.4. Добавим в процедуру обработчика код создания окна «Обложка».
Рис.20 |
2.6.5. Добавим в обработчик события диалога Ввод данных создание окна Обложка.
Перейдем в обработчик, далее ShiftCtrlW, установим в появившемся диалоге (п. 2.5) флаг User Defined Windows, выберем окно Обложка и нажмем. ОК. Будет вставлен код:
%BEGIN Ввод данных, idc_видобл _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_видобл,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
win_обложка_Create(_Win),
!.
%END Ввод данных, idc_видобл _CtlInfo
Теперь при нажатии ОблОткрыть будет выводиться окно Обложка. Для закрытия нужно нажать соответствующую пиктограмму.
2.6.6. В обработчик нажатия кнопки введем код, который получит файл, где хранится обложка, изменит видимость кнопок ОблОткрыть и ОблЗакрыть, прочитает дескриптор окна Task и создаст в нем окно Обложки (для этого заменим . Win на TaskWin)
%BEGIN Ввод данных, idc_видобл _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_видобл,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
%Выберем файл обложки,
сохраним путь к нему в базе имяФайлаОбложки(),
%выведим имя файла в поле
Файл
ID_Обложка=win_GetCtlHandle(_Win,idc_обложка),
получимИмяОбложки(ID_Обложка),
%+Установим видимость кнопок
idc_видобл и idc_облзакрыть
ID_ОблОткрыть=win_GetCtlHandle(_Win,idc_видобл),
ID_ОблЗакрыть=win_GetCtlHandle(_Win,idc_облзакрыть),
win_SetState(ID_ОблОткрыть, [wsf_Disabled]),
win_SetState(ID_ОблЗакрыть, [wsf_Enabled]),
%-
%Прочитаем дескриптор окна
TaskWin
TaskWin
= vpi_GetTaskWin(),
%Создадим окно обложки в окне
TaskWin
win_обложка_Create(TaskWin),
!.
%END Ввод данных, idc_видобл _CtlInfo
Приведем текст инструментальной процедуры получимИмяОбложки(_Win).
Predicates
%Получает имя файла обложки
получимИмяОбложки(window ID_Обложка)
clauses
получимИмяОбложки(ID_Обложка):-
%Прочитаем имя файла в поле
Файл диалога
""=win_GetText(ID_Обложка),
%Продолжим если файл еще не
выбран
!,
%Выберим файл с видом
обложки
выбратьФайл(ID_Обложка),
!.
получимИмяОбложки(ID_Обложка):-
%Прочитаем новое имя файла
0
= dlg_Ask("","Выбрать новую
обложку?",["&Да","&Нет"]),
%ANSWER =0,%Выберем новую
обложку
%Выберим файл с видом
обложки
выбратьФайл(ID_Обложка),
!.
получимИмяОбложки(_).
А также текст внутренней процедуры выбратьФайл(ID_Обложка)
predicates
%Выбирает имя файла обложки,
сохраняет полный путь к нему
%Выводит только имя файла в
поле Файл диалога
выбратьФайл(window
ID_Обложка)
clauses
выбратьФайл(ID_Обложка):-
%Выберем имя файла
_FILENAME
=
dlg_GetFileName("*.bmp",["bmp","*.bmp","pre","*.pre"],
"Выберите
файл с картинкой обложки",[],"",_OutListFiles),
%Запомним имя файла
assert(имяФайлаОбложки(_FILENAME),Рабочая),
%Получим Имя файла
filenamepath(_FILENAME,_Path,Name),
%Занесем имя выбранного
файла в поле Файл
win_SetText(ID_Обложка, Name).
Полное имя файла временно сохраняется в базе имяФайлаОбложки
рабочей области. Описание базы делается в файле ОписаниеРабБаз.pro:
facts – Рабочая
….
single имяФайлаОбложки(string ИмяФайла)
…..
Clauses
…..
имяФайлаОбложки("").
2.6.7.
Создадим обработчик события обновления окна Обложка (Окно Проекта->Windows-Обложка-CodeExpert-Window- e_Update-AddClause).
При наступлении этого события прорисовывается рисунок обложки.
%BEGIN Обложка, e_Update
win_обложка_eh(_Win,e_Update(_UpdateRct),0):-!,
!.
%END Обложка, e_Update
2.6.8. Занесем в обработчик код для вывода рисунка обложки.
Ниже приведенный код изменяет
размеры окна под размеры рисунка и выводит окно в правую верхнюю часть окна Task.
%BEGIN Обложка, e_Update
win_обложка_eh(_Win,e_Update(_UpdateRct),0):-!,
запомнитьОкноОбложки(_Win),
%Прочитаем имя файла обложки
имяФайлаОбложки(ИмяФайлаОбложки),
%Загрузи картинку в память
Picture=pict_Load(ИмяФайлаОбложки),
%Прочитаем дескриптор окна
Task
TaskWin =
vpi_GetTaskWin(),
%Получим его размеры
ClntRCT1=win_GetClientRect(TaskWin),
%Найдем правую границу окна
ClntRCT1=rct(_,_,_ПраваяГраница,_),
%Прочитаем размеры картинки
pict_GetSize(Picture, Width, Height,
_Size),
%Переместим окно обложки в правый верхний
угол окна Task
%Рассчитаем границы
СмещениеСверху=50,ОтступСправа=30,
ЛеваяГраница=_ПраваяГраница-Width-ОтступСправа,
Высота=Height+СмещениеСверху,
Ширина=ЛеваяГраница+Width,
win_Move(_Win,rCT(ЛеваяГраница,СмещениеСверху,Ширина,Высота)),
%Выведем картинку в окно
pict_Draw( _Win,Picture,
rCT(0,0,Width,Height), rct(0,0, Width,Height),rop_SrcCopy),
%Очистим память от картинки
pict_Destroy(Picture),!.
%END Обложка, e_Update
Запишем в файл ПроцПользователя.pro используемую в обработчике e_Update процедуру запомнитьОкноОбложки. Она запоминает в базе данных iD_ОкнаОбложки дескриптор окна обложки и состояние (открыто/закрыто):
predicates
запомнитьОкноОбложки(window)
clauses
запомнитьОкноОбложки(Win):-
%Окно обложки закрыто?
iD_ОкнаОбложки(_,b_false),
%Да,установим признак, что
окно открыто
retract(iD_ОкнаОбложки(_,_),Рабочая),
assert(iD_ОкнаОбложки(Win,b_true),Рабочая),
!.
запомнитьОкноОбложки(_Win). %Окно уже открыто
2.7. Создадим обработчик события нажатия кнопки ЗакрытьОбложку.
%BEGIN Ввод данных, idc_облзакрыть _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_облзакрыть,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
!.
%END Ввод данных, idc_облзакрыть _CtlInfo
2.7.1. Введем в обработчик ЗакрытьОбложку код, который удалит окно обложки и изменит видимость кнопок ВидОбложки и ЗакрытьОбложку.
%BEGIN Ввод данных,
idc_облзакрыть _CtlInfo
dlg_ввод_данных_eh(_Win,e_Control(idc_облзакрыть,_CtrlType,_CtrlWin,_CtlInfo),0):-!,
удалитьОкноОбложки,
%Установим видимость кнопок работы с обложкой
ID_ОблОткрыть=win_GetCtlHandle(_Win,idc_видобл),
ID_ОблЗакрыть=win_GetCtlHandle(_Win,idc_облзакрыть),
win_SetState(ID_ОблОткрыть, [wsf_Enabled]),
win_SetState(ID_ОблЗакрыть, [wsf_Disabled]),
!.
%END Ввод данных, idc_облзакрыть _CtlInfo
2.7.2. Создадим код процедуры удалитьОкноОбложки.
predicates
удалитьОкноОбложки
clauses
удалитьОкноОбложки:-
%Окно обложки открыто?
iD_ОкнаОбложки(Window,b_true),
%Да, установим признак, что
окно закрыто
retract(iD_ОкнаОбложки(_,_),Рабочая),
assert(iD_ОкнаОбложки(Window,b_false),Рабочая),
%Закроем окно
win_Destroy(Window),!.
удалитьОкноОбложки.
2.8. Создадим окно Просмотр с элементом диалога Список для удаления/редактирования/вывода базы Литература (рис. 9).
Оно имеет:
· меню с пунктами Удалить, Редактировать, Просмотр карточки книги и стандартный пункт Window.
· панель инструментов с недоступными пиктограммами: Удалить, Редактировать и Просмотр карточки книги в окне сообщений.
· элемент диалога Список в рабочей области окна. Сюда выводится список литературы;
· панель справки (в нижней части окна).
Панель инструментов становится доступной после выбора в списке книги.
У родительского окна (Task) удалены панели инструментов и справки. Они восстанавливаются при закрытии окна Просмотр.
При вызове пункта Удаление/Редактирование/Вывод главного меню открывается окно Просмотр со списком литературы. Оператор выбирает нужную книгу. После этого становятся доступными операции удаления, редактирования и вывода карточки книги. Карточка выводится в окно сообщений или в файл с именем карточка.txt. При редактировании записи открывается ранее созданный диалог.
2.8.1. Создадим пиктограммы для панели инструментов окна Просмотр.
На панели инструментов выбираем Bitmap-New. Для каждой пиктограммы создадим 3 рисунка с пиктограммами не нажатой, нажатой и недоступной клавишей, сохранив их в файлах. Например: Cut_UP.bmp, Cut_Down.bmp, Cut_Gray.bmp. На рис. 21 показан возможный вид рисунков пиктограмм для редактирования записи.
2.8.2. Создадим меню окна Просмотр с пунктами Удалить, Редактировать и Просмотр карточки. Установим атрибут недоступности для этих пунктов.
2.8.3. Создадим панель инструментов ИнсПросмотра.
На панели инструментов выбираем ToolBar-New. Разместим на ней пиктограммы инструментов. Установим флаг недоступности для этих пиктограмм.
2.8.4. Создадим окно ПросмотрСписка.
Создание окна описано в п. 2.6.1.
2.8.5. Разместим в этом окне элемент диалога ListBox и установим флаги:
wsf_Sort, wsf_NoBorder остальные примем по умолчанию (размер элемента диалога значения не имеет т.к. по умолчанию он будет по размеру окна).
2.8.6. Создадим обработчик создания окна ПросмотрСписка.
%BEGIN ПросмотрСписка, e_Create
win_просмотрсписка_eh(_Win,e_Create(_),0):-!,
%BEGIN ПросмотрСписка, InitControls, 17:25:44-29.5.2014,
Code automatically updated!
win_CreateControl(wc_LBox,rct(2,6,820,158),"",_Win,[wsf_Group,wsf_TabStop,wsf_VScroll,wsf_Sort,wsf_NoIntegralHeight,wsf_NoBorder],idc_listbox),
%END ПросмотрСписка, InitControls
%BEGIN ПросмотрСписка, ToolbarCreate, 17:25:44-29.5.2014,
Code automatically updated!
%END ПросмотрСписка, ToolbarCreate
!.
%END ПросмотрСписка, e_Create
При создании окна предикатом win_CreateControl будет создан код для элемента управления (списка). Поясним список параметров для окна ПросмотрСписка:
win_CreateControl(
wc_LBox, %тип элемента диалога
rct(2,6,820,158), %Размер списка
"", %Заголовок
_Win, %родительское окно
[wsf_Group, %Флаг для начала создания новой группы %элементов управления
wsf_TabStop, %Позволить переход по табуляции к элементу управления
wsf_VScroll, %при необходимости будет иметь вертикальную полосу прокрутки
wsf_Sort, %Сортирует строки в списке в алфавитном порядке
wsf_NoIntegralHeight, %Определяет, что размер окна списка — тот размер, который указан при создании списка.
wsf_NoBorder], % элемент управления не должен иметь границу
idc_listbox),
2.8.7. Добавим в проект код создания панелей инструментов ИнсПросмотра и Справки.
На панели инструментов выбираем ToolBar- ИнсПросмотра- CodeExpert. На появившейся панели задаем:
Рис. 22 |
После нажатия кн. DefaultCode на этой панели будет создан код
%BEGIN_TLB ИнсПросмотра, 11:12:58-5.5.2015, Code
automatically updated!
/**************************************************************************
Creation
of toolbar: ИнсПросмотра
**************************************************************************/
clauses
tb_инспросмотра_Create(_Parent):-
ifdef use_tbar
toolbar_create(tb_top,0x808080,_Parent,
[tb_ctrl(idt_Удалить,pushb,idb_cut_up,idb_cut_dn,idb_cut_gray,"Delete",0,1),
tb_ctrl(idt_Редактировать,pushb,idb_edit_up,idb_edit_down,idb_edit_gray,"Edit",0,1),
tb_ctrl(idt_Карточка,pushb,idb_card_up,idb_copy_dn,idb_card_gray,"Card",0,1)]),
enddef
true.
%END_TLB ИнсПросмотра
Также в соответствующую секцию программы будет добавлен код создания панелей инструментов и справки в окно ПросмотрСписка.
%BEGIN ПросмотрСписка, ToolbarCreate, 11:12:44-5.5.2015,
Code automatically updated!
tb_инспросмотра_Create(_Win),
tb_help_line_Create(_Win),
%END ПросмотрСписка,
ToolbarCreate
В обработчик события изменения размера окна ПросмотрСписка будет введен код обновления введенных панелей:
toolbar_Resize(_Win)
2.8.8. Добавим дополнительный код в обработчик события окна ПросмотрСписка.
Этот код удалит панели инструментов и справки родительского окна (Task) и выведет список литературы в окно в непропорциональном шрифте.
%BEGIN ПросмотрСписка, e_Create
win_просмотрсписка_eh(_Win,e_Create(_),0):-!,
%BEGIN ПросмотрСписка, InitControls, 11:12:44-5.5.2015, Code automatically updated!
win_CreateControl(wc_LBox,rct(2,6,820,158),"",_Win,[wsf_Group,wsf_TabStop,wsf_VScroll,wsf_Sort,wsf_NoIntegralHeight,wsf_NoBorder],idc_listbox),
%END ПросмотрСписка, InitControls
%Удалим панель инструментов
родительского окна
%Прочитаем дескриптор
родительского окна
ParentWin
= win_GetParent(_Win),
%Удалим панель инструментов этого
окна
toolbar_remove(ParentWin),
%Получим ID списка
LBWIN
= win_GetCtlHandle(_Win, idc_listbox),
%Установим непропорциональный
шрифт
Font=font_Create(ff_Fixed,
[], 10),
win_SetFont(LBWIN,Font),
%С формируем заголовок окна
win_SetText(_Win,"Выделите
строку для операции" ),
%Выведем список в окно
заполнитьСписок(LBWIN),
%BEGIN ПросмотрСписка, ToolbarCreate, 11:12:44-5.5.2015, Code automatically updated!
tb_инспросмотра_Create(_Win),
tb_help_line_Create(_Win),
%END ПросмотрСписка, ToolbarCreate
!.
%END ПросмотрСписка, e_Create
2.8.9. Создадим текст инструментальной процедуры заполнитьСписок(LBWIN).
В этой процедуре перед добавление в список записи базы данных выполняется ее форматирование.
predicates
заполнитьСписок(window
ID_ОкнаСписка)
clauses
заполнитьСписок(ID_ОкнаСписка):-
%Прочитает очередную запись из базы данных литературы
база_лит(Код,
Автор,
Наименование,
Категория,
Диск,
Переплет,
Обложка),
%Отформатируем запись
format(OutputVariable,"%5.5|%-20.18|%-30.25|%10.10|%4.4|%4.4|%10.10",
Код,
Автор,
Наименование,
Категория,
Диск,
Переплет,
Обложка),
%Добавим очередную строку в
конец списка (параметр -1) ID_ОкнаСписка
lbox_Add(ID_ОкнаСписка, -1, OutputVariable),
fail.
заполнитьСписок(_ID_ОкнаСписка).
2.8.10. Откроем доступ к меню и панели инструментов окна ПросмотрСписка.
Добавим код в обработчик события выбора элемента списка в окне ПросмотрСписка. Перейдем в эксперт окон, выберем тип события Control и событие selchanged. Добавим обработчик этого события, а нем необходимый код:
%BEGIN ПросмотрСписка,
idc_listbox selchanged
win_просмотрсписка_eh(_Win,e_Control(idc_listbox,_CtrlType,_CtrlWin,selchanged),0):-!,
%Установим видимость панели
инструментов
Видимость=b_True,
toolbar_SetValue(_Win, idt_Удалить, ctrl_value(Видимость,1)),
toolbar_SetValue(_Win, idt_Редактировать, ctrl_value(Видимость,1)),
toolbar_SetValue(_Win, idt_Карточка, ctrl_value(Видимость,1)),
%Установим видимость меню
окна
menu_Enable(_Win,
idr_удалить, Видимость),
menu_Enable(_Win,
idr_редактировать_базу, Видимость),
menu_Enable(_Win,
idr_вывести_карточку, Видимость),
menu_Update(_Win),
win_Update(_Win),
!.
%END ПросмотрСписка,
idc_listbox selchangedСоздадим обработчик события
2.8.11. Создадим код обработки события Удалить запись базы данных.
%BEGIN
ПросмотрСписка, idr_удалить
win_просмотрсписка_eh(_Win,e_Menu(idr_удалить,_ShiftCtlAlt),0):-!,
!.
%END
ПросмотрСписка, idr_удалить
2.8.12. Добавим в обработчик события Удалить инструментальный код, который прочитает индекс выделенной строки, удалит строку после подтверждения операции.
Создадим в области Рабочая описание базы для хранения выделенного элемента из списка
determ выделенныеЭлементыСпискаПросмотра (window ID_Списка,
slist
СписокВыделенныхЭлементов,
ilist
СписокНомеровВыделенныхЭлементов)
Добавим в начало основного файл проекта установку в начальное состояние этой базы.
%Установим в нач.состояние список выделенных
элментов в списке просмотра
assert(выделенныеЭлементыСпискаПросмотра(_Win,[],[]),Рабочая),
%BEGIN ПросмотрСписка,
idr_удалить
win_просмотрсписка_eh(_Win,e_Menu(idr_удалить,_ShiftCtlAlt),0):-!,
%Прочитаем список на удаление
LBWIN = win_GetCtlHandle(_Win, idc_listbox),
lbox_GetSel(LBWIN,_ItemList,_IndexList),
естьВыделенныеСтроки(_IndexList),
%ДА
%Запомним ID_Списка и Списки
строк и номеров элемента диалога
retract(выделенныеЭлементыСпискаПросмотра(_,_,_),Рабочая),
assert(выделенныеЭлементыСпискаПросмотра(LBWIN,_ItemList,_IndexList),Рабочая),
%Продолжим, если список не
пуст
ANSWER =
dlg_Ask("Удаление строки",
"Удалить
выделенную строку"/*Prompt*/,
["Да","Продолжить","Выход"]/*ButtonTitlesList*/),
обработатьОтветНаУдаление(_Win,/*_IndexList,*/ANSWER),
!.
win_просмотрсписка_eh(_Win,e_Menu(idr_удалить,_ShiftCtlAlt),0):-!.
%END ПросмотрСписка,
idr_удалить
2.8.13. Создадим коды инструментальных процедур используемых в обработчике.
Представленый код можно использовать для удаления несколько выделенных элементов.
predicates
естьВыделенныеСтроки(ilist
СписокВыделенныхСтрок)
clauses
естьВыделенныеСтроки([]):-
_Answer =
dlg_MessageBox( "Ошибка!",
"Не
выделена\nстрока в списке", mesbox_iconError,
mesbox_buttonsOK,
mesbox_defaultfirst, mesbox_suspendapplication ),
!,fail.
естьВыделенныеСтроки(_).
predicates
обработатьОтветНаУдаление(window Win,/*ilist
IndexList*/integer ANSWER)
clauses
обработатьОтветНаУдаление(_Win,/*IndexList,*/0):-
%Удалить!
%Получим список строк на
удаление
выделенныеЭлементыСпискаПросмотра(_ID_Списка,СписокВыделенныхЭлементов,IndexList),
%Удалим из списка элемент по
его номеру Ном
IndexList=[Ном],
lbox_Delete(_ID_Списка, Ном),
удалитИзОсновнойБазыПоСписку(СписокВыделенныхЭлементов),
!.
обработатьОтветНаУдаление(_Win,1):-!.
%Вернуться к выделению!
2.8.14. Добавим обработчик события выбора элемента Удалить панели инструментов окна ПросмотрСписка и запишем необходимый инструментальный код. Очевидно, он будет совпадать с кодом обработчика события Удалить пункта меню.
Выберем в окне проекта Window-ПросмотрСписка-CodeExpert-Menu-idt_Удалить и AddClauses. Будет создан обработчик:
%BEGIN ПросмотрСписка,
idt_Удалить
win_просмотрсписка_eh(_Win,e_Menu(idt_Удалить,_ShiftCtlAlt),0):-!,
!.
%END ПросмотрСписка, idt_Удалить
Затем скопируем код из обработчика события Удалить пункта меню во вновь созданный обработчик.
2.8.15. Создадим обработчик события выбора пункта меню Редактировать.
Как было описано выше для редактирования будем использовать ранее созданный диалог ввода данных (рис. ). Для этого внесем в код обработчика создания окна диалога определенные изменения.
2.8.15.1. Добавим в ранее созданный обработчик код, который обеспечит его запуск только в режиме ввода данных. Для этого используем базу (флаг) устРежимРаботыСБазой(ввода) .Флаг принимает значения «ввод» или «редактирование». Если он в состоянии «ввод», то выполняется ранее созданный обработчик:
%BEGIN Ввод данных, e_Create
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-%!, !!!!
устРежимРаботыСБазой(ввода),!,
….
Обязательно нужно убрать отсечение закомментированное выше !!!!
Если флаг в состоянии «редактирование», то выполняется иной код, который заполнит диалоговое окно в соответствии с выбранной из списка записью.
2.8.15.2. Создадим обработчик для случая редактирования записи. Разместим его сразу после ранее созданного обработчика.
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-!,
устРежимРаботыСБазой(редактирование),
%Прочитаем
Код выделенного элемента списка
выделенныеЭлементыСпискаПросмотра(_ID_Списка,
СписокВыделенныхЭлементов,
_СписокНомеровВыделенныхЭлементов),
%Найдем
код выделенного элемента
СписокВыделенныхЭлементов=[ЭлементСписка],
frontstr(5,ЭлементСписка,СтрокаКода,_),
%Преобразуем
СтрокаКода в число
str_int(СтрокаКода,Код),
база_лит(
Код,Автор,Наименование,
_Категория,
_Диск,
_Переплет,
Обложка),
%+Установим
значения элементов диалога
установимТекстЭлДиалога(_Win
,idc_автор, Автор),
установимТекстЭлДиалога(_Win
,idc_наименование, Наименование),
установимСостояниеЭлДиалога(_Win,idc_диск,_Диск),
установимСостояниеЭлДиалогаПереплет(_Win,_Переплет),
установимТекстЭлДиалога(_Win
,idc_обложка, Обложка),
%Загрузим
список категорий
findall(КатегорияЛит,категории_лит(КатегорияЛит),
ListКатегорияЛит ),
sort(ListКатегорияЛит,ListКатегорияЛит1),
ID_Категория=win_GetCtlHandle(_Win,категория),
lbox_Add(ID_Категория,
0, ListКатегорияЛит1),
найтиЭлСпискаПоНомеру(ListКатегорияЛит1,_Категория,0,Номер),
%Покажем в списке элем.диалога первый элемент
lbox_SetSel(ID_Категория,Номер,b_True),
%Установим
фокус на поле Автор
ID_Автор=win_GetCtlHandle(_Win,idc_автор),
win_SetFocus(ID_Автор),
!.
%END Ввод данных, e_Create
Приведем тексты инструментальных процедур, которые используются в обработчике. Они установят состояния и текст в элементах диалога ВводаДанных:
predicates
установимСостояниеЭлДиалога(window ОкноДиалога,integer Id,integer Состояние)
установимТекстЭлДиалога(window ОкноДиалога,integer Id, string Текст)
установимСостояниеЭлДиалогаПереплет(window
_Win,integer Переплет)
clauses
установимСостояниеЭлДиалога(Win,Id,Состояние):-
ID_Элемента=win_GetCtlHandle(Win,Id),
win_Check(ID_Элемента,Состояние).
%Состояние=win_IsChecked(ID_Элемента).
установимТекстЭлДиалога(Win,Id,Текст):-
ID_Элемента=win_GetCtlHandle(Win,Id),
win_SetText(ID_Элемента,
Текст).
установимСостояниеЭлДиалогаПереплет(Win,b_false):-
установимСостояниеЭлДиалога(Win,idc_мягкий,b_true),
установимСостояниеЭлДиалога(Win,idc_твердый,b_false),!.
установимСостояниеЭлДиалогаПереплет(Win,b_true):-
установимСостояниеЭлДиалога(Win,idc_мягкий,b_false),
установимСостояниеЭлДиалога(Win,idc_твердый,b_true).
/* номер позиции элемента*/
PREDICATES
найтиЭлСпискаПоНомеру(slist,string,integer,integer)
clauses
clauses
найтиЭлСпискаПоНомеру([],_,0,0):-!.
найтиЭлСпискаПоНомеру([Элем|T],Критерий,Поз,ПозЭл):-
Критерий<>Элем,Поз1=Поз+1,
найтиЭлСпискаПоНомеру(T,Критерий,Поз1,ПозЭл),!.
найтиЭлСпискаПоНомеру(_,_,ПозЭл,ПозЭл).
2.8.15.3. Добавим в обработчик события выбора пункта Ввод данных начальную установку флага в состояние «ввод».
%BEGIN Task Window,
id_База_ввод_данных
task_win_eh(_Win,e_Menu(id_База_ввод_данных,_ShiftCtlAlt),0):-!,
%Запомним
режим работы с основной базой
assert(устРежимРаботыСБазой(ввода)),
%Активизируем диалог ввода данных
dlg_ввод_данных_Create(_Win),
!.
%END Task Window, id_База_ввод_данных
2.8.15.4. Добавим в обработчик код при выборе пункта Редактировать окна ПросмотрСписка и введем в него код, который запоминает дескриптор элемента диалога Список, выделенные строки (если их несколько) и их индексы и вызывает создание диалога Ввод_данных. Созданный в примере элемент диалога Список (idc_listbox) не поддерживает выбор нескольких строк)
%BEGIN ПросмотрСписка,
idr_редактироватьбазу
win_просмотрсписка_eh(_Win,e_Menu(idr_редактироватьбазу,_ShiftCtlAlt),0):-!,
%Установим флаг режима диалога ввода данных в состояние
"редактирование"
assert(устРежимРаботыСБазой(редактирование)),
%Прочитаем выделенный список
LBWIN = win_GetCtlHandle(_Win, idc_listbox),
lbox_GetSel(LBWIN,_ItemList,_IndexList),
lbox_GetSel(LBWIN,_ItemList,_IndexList),
естьВыделенныеСтроки(_IndexList),
%Да
%Запомним ID_Списка и Списки
строк и номеров элемента диалога
retract(выделенныеЭлементыСпискаПросмотра(_,_,_),Рабочая),
assert(выделенныеЭлементыСпискаПросмотра(LBWIN,_ItemList,_IndexList),Рабочая),
dlg_ввод_данных_Create(_Win),
!.
%END ПросмотрСписка,
idr_редактироватьбазу
2.8.16. Добавим обработчик выбора элемента Редактировать панели инструментов окна ПросмотрСписка.
Очевидно, этот код будет совпадать с кодом обработчика при выборе пункта меню Редактировать этого окна.
%BEGIN ПросмотрСписка, idt_Редактировать
win_просмотрсписка_eh(_Win,e_Menu(idt_Редактировать,_ShiftCtlAlt),0):-!,
%Установим флаг режима
диалога ввода данных в состояние "редактирование"
assert(устРежимРаботыСБазой(редактирование)),
%Прочитаем выделенный список
LBWIN = win_GetCtlHandle(_Win, idc_listbox),
lbox_GetSel(LBWIN,_ItemList,_IndexList),
естьВыделенныеСтроки(_IndexList),
%Да
%Запомним ID_Списка и Списки
строк и номеров элемента диалога
retract(выделенныеЭлементыСпискаПросмотра(_,_,_),Рабочая),
assert(выделенныеЭлементыСпискаПросмотра(LBWIN,_ItemList,_IndexList),Рабочая),
dlg_ввод_данных_Create(_Win),
!.
%END ПросмотрСписка, idt_Редактировать
2.8.17. Добавим код создания диалога ВводаДанных при редактировании выделенного элемента строки. Он должен прочитать данные выделенной в окне списка записи и отобразить ее в элементах диалога.
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-!,
устРежимРаботыСБазой(редактирование),
%Прочитаем Код выделенного
элемента списка
выделенныеЭлементыСпискаПросмотра(_ID_Списка,
СписокВыделенныхЭлементов,
_СписокНомеровВыделенныхЭлементов),
%Найдем код выделенного
элемента
СписокВыделенныхЭлементов=[ЭлементСписка],
frontstr(5,ЭлементСписка,СтрокаКода,_),
%Преобразуем СтрокаКода в число
str_int(СтрокаКода,Код),
база_лит(
Код,Автор,Наименование,
_Категория,
_Диск,
_Переплет,
Обложка),
%+Установим значения
элементов диалога
установимТекстЭлДиалога(_Win
,idc_автор, Автор),
установимТекстЭлДиалога(_Win
,idc_наименование, Наименование),
установимСостояниеЭлДиалога(_Win,idc_диск,_Диск),
установимСостояниеЭлДиалогаПереплет(_Win,_Переплет),
установимТекстЭлДиалога(_Win
,idc_обложка, Обложка),
%Загрузим список категорий
findall(КатегорияЛит,категории_лит(КатегорияЛит),
ListКатегорияЛит ),
sort(ListКатегорияЛит,ListКатегорияЛит1),
ID_Категория=win_GetCtlHandle(_Win,категория),
lbox_Add(ID_Категория,
0, ListКатегорияЛит1),
найтиЭлСпискаПоНомеру(ListКатегорияЛит1,_Категория,0,Номер),
%Покажем в списке
элем.диалога первый элемент
lbox_SetSel(ID_Категория,Номер,b_True),
%Установим фокус на поле
Автор
ID_Автор=win_GetCtlHandle(_Win,idc_автор),
win_SetFocus(ID_Автор),
!.
%END Ввод данных, e_Create
2.8.18. Добавим в код создания диалога ВводДанных при вводе данных (см. выше п. 2.2.8) блокировку.
%BEGIN Ввод данных, e_Create
dlg_ввод_данных_eh(_Win,e_Create(_CreationData),0):-!,
устРежимРаботыСБазой(ввода),!,
%Установим значения
элементов диалога
%Загрузим список категорий
findall(КатегорияЛит,категории_лит(КатегорияЛит),ListКатегорияЛит
),
2.9. Создадим пункт меню Настройки.
Он будет использоваться для установки шрифта по умолчанию для вывода карточки в окно сообщений.
2.9.1. Создадим базу для хранения текущего шрифта.
Опишем в файле ОписаниеРабБаз.pro базу:
/**************Описание базы настроек******************/
facts - Настройки
determ
шрифтКарточки(font ПарамертыШрифта)
/******************************************************/
Занесем в начало главного файла проектабазу код записи шрифта по умолчанию (шрифт окна Task):
…
%Запомним текущий шрифт
окна.
%Он
используется по умолчанию
%при
выводе карточки в окно сообщений
Font = win_GetFont(_Win),
assert(шрифтКарточки(
Font),Настройки),
ifdef use_message
msg_Create(100),
enddef
2.9.2. Создадим пункт меню Настройки в главном меню проекта и обработчик события его выбора, а также инструментальный код, который прочитает шрифт хранящийся в базе шрифтКарточки(_), выведет диалог выбора шрифта и запомнит его.
%BEGIN Task Window, id_настройки
task_win_eh(_Win,e_Menu(id_настройки,_ShiftCtlAlt),0):-!,
%Прочитаем
ранее установленный шрифт
шрифтКарточки(
OldFONT),
%Выберем новый шрифт
_NewFONT=dlg_ChooseFont(OldFONT),
%Сохраним новый шрифт
retractall(шрифтКарточки(_),Настройки),
assert(шрифтКарточки(
_NewFONT),Настройки),
save(имяБазыНастроек,настройки),
!.
%END Task Window,
id_настройки
2.9.3. Создадим обработчик события выбора пункта меню ВыводКарточки окна ПросмотрСписка и инструментальный код, который проверит, есть ли выделенные строки в списке окна, прочитает запись из базы литературы, запишет эту запись в файл "карточка.txt", а затем результат записи в файл выведет в окно сообщений.
Для записи в файл будем использовать файловый домен myfile. Добавим в раздел User's Declarations файла ИмяГлавногоФайлаПроекта.inc объявление файлового домена myfile. Он будет использоваться для работы с файлом карточки. Для перехода к этому файлу выделите главный файл в окне проекта и вызовите контекстное меню, затем файл *.inc и пункт Edit и добавить необходимый код:
/*****************************************************************************
User's
Declarations
*****************************************************************************/
global domains
DB_SELECTOR = browselist_db %
For treebrowser tool
FILE =
fileselector1; fileselector2;myfile % To be edited
Создадим обработчик и инструментальный код:
%BEGIN ПросмотрСписка,
idr_вывести_карточку
win_просмотрсписка_eh(_Win,e_Menu(idr_вывести_карточку,_ShiftCtlAlt),0):-!,
вывестиКарточку(_Win),
!.
%END ПросмотрСписка,
idr_вывести_карточку
Приведем текст используемых процедур вывестиКарточку(_Win) и создадимОкноСообщКарточки, которые разместим в файле ПроцПользователя.pro:
predicates
nondeterm вывестиКарточку(window _Win)
clauses
вывестиКарточку(_Win):-
%Прочитаем выделенный список
LBWIN = win_GetCtlHandle(_Win, idc_listbox),
lbox_GetSel(LBWIN,_ItemList,_IndexList),
естьВыделенныеСтроки(_IndexList),
%Да
%Запомним ID_Списка и Списки строк и
номеров элемента диалога
retract(выделенныеЭлементыСпискаПросмотра(_,_,_),Рабочая),
assert(выделенныеЭлементыСпискаПросмотра(LBWIN,_ItemList,_IndexList),Рабочая),
_ItemList=[ЭлементСписка],
frontstr(5,ЭлементСписка,СтрокаКода,_),
%Преобразуем СтрокаКода в число
str_int(СтрокаКода,Код),
база_лит(
Код,Автор,Наименование, _Категория,_Диск,_Переплет,
Обложка),
%откроем канал к рабочему файлу
%канал myfile обьявить в файле
ИмяПроекта.inc
openwrite(myfile,"карточка.txt"),
%зададим канал в качестве текущего
writedevice(myfile),
%вывести_базу в файл
writef("Автор:\t\t\t%
",Автор),nl,
writef("Наименование:\t\t%
",Наименование),nl,
writef("Категория:\t\t%
",_Категория),nl,
%+Получим по коду вид
переплета и наличие диска
вид_переплета(
_Переплет, ВидПереплета),
наличиеДиска(
_Диск,Наличие),
%-
writef("Диск:\t\t\t%
",Наличие),nl,
writef("Переплет:\t\t%
",ВидПереплета),nl,
writef("Обложка:\t\t%
",Обложка),nl,
%закроем файл
closefile(myfile),
%прочитаем рабочий файл в переменную
Text
file_str("карточка.txt",Text),
%Переключимся на экран
writedevice(screen),
%Выведем карточку в окно сообщений
создадимОкноСообщКарточки,
write(Text),
write("______________________________________________"),nl.
predicates
создадимОкноСообщКарточки
clauses
создадимОкноСообщКарточки:-
Win=msg_GetWin(),
%Окно
есть!.
%Установим
шрифт
шрифтКарточки(
Font),
win_SetFont(Win,Font),!.
создадимОкноСообщКарточки:-
%Окна
нет. Создадим его.
msg_Create(40),
Win=msg_GetWin(),
%Установим
шрифт
шрифтКарточки(
Font),
win_SetFont(Win,Font).
2.9.4. Создадим обработчик события выбора пиктограммы ВыводКарточки окна ПросмотрСписка и инструментальный код.
Очевидно, инструментальный код будет полностью совпадать с кодом при выборе одноименного пункта меню.
%BEGIN ПросмотрСписка, idt_Карточка
win_просмотрсписка_eh(_Win,e_Menu(idt_Карточка,_ShiftCtlAlt),0):-!,
вывестиКарточку(_Win),
!.
%END ПросмотрСписка, idt_Карточка
2.9.5. Восстановим панель инструментов окна проекта.
Для этого создадим обработчик события удаления окна ПросмотрСписка и введем соответствующий инструментальный код.
%BEGIN ПросмотрСписка, e_Destroy
win_просмотрсписка_eh(_Win,e_Destroy,0):-!,
ParentWin = win_GetParent(_Win),
tb_project_toolbar_Create(ParentWin),
!.
%END ПросмотрСписка, e_Destroy
Добавим в последний предикат процедуры fail:
обработатьОтветНаУдаление(_Win,1):-!,fail.
2.10. Создадим диалоговое окно для вывода сообщения о сохранении данных.
Окно должно появляться при нажатии кнопки ОК диалога ВводДанных и через определенный интервал исчезать. Воспользуемся для этого таймером.
2.10.1. Создадим диалог.
В окне проекта выбираем: Dialog-New. Задаем его имя, тип (модальный), если нужна необходимые флаги. После нажатия ОК удалим кнопки окна, создадим статический текст «Данные сохранены». Если необходимо установим флаги элемента диалога (по центру и т.п.). Используя окно Атрибутов диалога установим размер шрифта.
Рис. 23 |
Рис. 24 |
2.10.2. Добавим в обработчик нажатия ОК диалога ВводДанных процедуру вывода диалога информационного сообщения:
dlg_ввод_данных_eh(_Win,e_Control(idc_ok,_CtrlType,_CtrlWin,_CtlInfo),0):-%!,
…
%Запишем новые данные
asserta(база_лит(КодНовый,_Автор,_Наименование,_Категория,_Диск,_Переплет,_Обложка),Литература),
save(имяБазыЛит,Литература),
dlg_инфсохранена_Create(_Win),
%установлен
режим редактирования?
устРежимРаботыСБазой(редактирование),
…
2.10.3. Добавим обработчик события создания диалога вывода сообщения и в нем вызов инструментальной процедуры запуска таймера стартТаймера(_Win).
%BEGIN ИнфСохранена, e_Create
dlg_инфсохранена_eh(_Win,e_Create(_CreationData),0):-!,
стартТаймера(_Win),
!.
%END ИнфСохранена, e_Create
Текст процедуры стартТаймера(_Win) представлен ниже. В ней используется счетчикПрерывТаймера(integer КолПрерываний), который предварительно должен быть установлен в 0.
facts - Рабочая
…
single
счетчикПрерывТаймера(integer КолПрерываний)
…
clauses
счетчикПрерывТаймера(0).
…
%Начальный запуск таймера
PREDICATES
стартТаймера(window)
CLAUSES
стартТаймера(_Win):-
%обнулим
счетчик прерываний таймера
assert(счетчикПрерывТаймера(0),Рабочая),
%Запустим таймер с
интервалом 500 миллисекунд
_NewTimerID=timer_Set(_Win,500).
2.10.4. Добавим обработчик события таймера e_Timer и в нем код инструментальной процедуры обработкаСобытТаймера(_Win,_TimerID), который будет обрабатывать эти события. Эти события относятся к группе Misc.
%BEGIN ИнфСохранена,
e_Timer
dlg_инфсохранена_eh(_Win,e_Timer(_TimerId),0):-!,
обработкаСобытТаймера(_Win,_TimerID),
!.
%END ИнфСохранена, e_Timer
Текст процедуры обработкаСобытТаймера(_Win,_TimerID представлен ниже. В ней используется процедура
анализ
(window IDокна,long IDтаймера, integer КолСобытий)
PREDICATES
nondeterm
анализ (window IDокна,long IDтаймера, integer КолСобытий)
CLAUSES
анализ(_Win,_TimerID,2):-
%Удалим таймер и закроем окно
timer_Kill(_TimerID),
win_Destroy(_Win).
анализ
(_,_,_). %Пропустим событие таймера
PREDICATES
nondeterm
обработкаСобытТаймера(window IDокна,long IDтаймера)
nondeterm
считаемСобытияТаймера(integer КолСобытий)
CLAUSES
обработкаСобытТаймера(_Win,_TimerID):-
считаемСобытияТаймера(КолСобытий),
анализ
(_Win,_TimerID,КолСобытий),
win_Destroy(_Win).
считаемСобытияТаймера(КолСобытий):-
счетчикПрерывТаймера(БылоКолСобытий),
КолСобытий=БылоКолСобытий+1,
assert(счетчикПрерывТаймера(КолСобытий),Рабочая).