
Costas-Tyros_rus_MS
.pdf
16.1.dopaint
Класс dopaint будет разбираться с рисованием, и работает более или менее похоже на метод dopaint в Java. Создайте класс, назовите его dopaint и отключите Creates Objects. Вот объявление
класса:
% Файл dopaint.cl class dopaint
open core predicates
classInfo : core::classInfo. draw:(windowGDI).
invalidrectangle:(vpiDomains::rct) procedure (o). end class dopaint
Наконец, рис. 16.2 показывает реализацию dopaint.pro. Постройте приложение.
16.2.Управлениетаймером
Когда вы закрываете canvas, вы должны отключить таймер. Чтобы добиться этого, добавьте
onDestroy(W) : click::kill(W).
к DestroyListener в диалоговом окне Properties формы canvas.frm. Затем добавьте
onTimer(_Source, _TimerID) : dopaint::invalidRectangle(R), invalidate(R).
к TimeListener в диалоговом окне Properties формы canvas.frm. Наконец, добавьте обработчик собы тия
onPaint(_Source, _Rectangle, GDIObject) : dopaint::draw(GDIObject).
к PaintResponder в диалоговом окне Properties формы canvas.frm.
16.3.Как программа работает
Первое, что делает предикат draw(W) это рисует несколько лягушек на заднем плане. Лягушки загружаются следующим предикатом:
P= vpi::pictLoad("figs\\frogs.bmp"),
Конечно же, в папке figs у вас должен лежать файл frogs.bmp. Затем draw(W) получает изображение и маску змеи.
121

Предикат flipflop(Snake, Mask) разработан для поочерёдной смены двух изображений змеи, для получения иллюзии движения. Чтобы вставить змею на задний план, вы должны использовать маски. Если вы не помните, как это делать, прочтите главу 8 заново.
implement dopaint
open core, vpiDomains constants
className = "snake/snakestate". classVersion = "".
class facts yesno:integer := 0.
class predicates
flipflop:(picture Picture, picture Mask) determ (o, o).
clauses
classInfo(className, classVersion).
flipflop(Pict, Mask) : yesno= 0, yesno := 1,
Pict= vpi::pictLoad("figs\\n0.bmp"),
Mask= vpi::pictLoad("figs\\n0Mask.bmp"), !. flipflop(Pict, Mask) : yesno= 1,
yesno := 0,
Pict= vpi::pictLoad("figs\\n1.bmp"), Mask= vpi::pictLoad("figs\\n1Mask.bmp").
draw(W) :
P= vpi::pictLoad("figs\\frogs.bmp"), W:pictDraw(P, pnt(10, 10), rop_SrcCopy), flipflop(Snake, Mask), !, W:pictDraw(Mask, pnt(40, 50), rop_SrcAnd),
W:pictDraw(Snake, pnt(40, 50), rop_SrcInvert). draw(_).
invalidRectangle(rct(40, 50, 100, 100)). end implement dopaint
Рисунок 16.2 dopaint.pro
122

Глава 17: Текстовый редактор
Вэтой главе вы научитесь использовать классeditControl для создания текстового редактора.
•Создайте новый проект
Project Name: editor
UI Strategy: Object oriented GUI(pfc/gui)
•Добавьте пакет editControl, который находится в каталоге установки Visual Prolog. Вы берите пункт File/Add и ищите пакет в
Visual Prolog 7.x\pfc\gui\controls\editorControl.
•Постройте приложение. Затем создайте новую форму edform.frm в корне дерева проек та, как показано на рис. 17.3. Чтобы вставить элемент управления editorControl в форму, выберите custom control – пункт нестандартного элемента управления на прототипе фор мы; это кнопка с ключом Йале1 (Yale) (рис. 17.1); и затем выберите editorControl в диало говом окне, показанном на рис. 17.2. Постройте приложение. Смените название элемента управления на editorControl_ctl как показано на рис. 17.4.
Рисунок 17.1 Кнопка вставки нестандартного элемента управления
Рисунок 17.1 Диалоговое окно Choose Custom Control
1 Йале изобрёл этот вид ключа, который так сегодня популярен. Легенда гласит, что вскоре после его изобретения, Гудини смог пробиться через новое устройство. – прим. авт.
123

•Включите File/New и добавьте нижеприведённый фрагмент к нему.
onFileNew(S, _MenuTag) : F= edform::new(S), F:show().
17.1.Сохранениеизагрузкафайлов
Идите в дерево проекта и откройте форму editor.frm, если она ещё не открыта. Используйте диалоговое окно Properties для того, чтобы вставить фрагмент с рис. 17.5 в ClickResponder кнопки button::save_ctl; затем добавьте код, показанный на рис. 17.6 к ClickResponder кнопки but
ton::load_ctl. Это почти всё, что вам нужно сделать для создания функционирующего текстового редактора.
Рисунок 17.3 Форма с Edit Control
Рисунок 17.2 Свойства элемента управления
124

predicates
onSaveClick : button::clickResponder. clauses
onSaveClick(_Source) = button::defaultAction() : Txt= editorControl_ctl:getEntireText(), FName= vpiCommonDialogs::getFileName("*.*",
["Text", "*.txt"], "Save", [], ".", _X), !,
file::writeString(FName, Txt). onSaveClick(_Source) = button::defaultAction().
Рисунок 17.5 Код для onSave
predicates
onLoadClick : button::clickResponder. clauses
onLoadClick(_Source) = button::defaultAction() : FName= vpiCommonDialogs::getFileName("*.*",
["Text", "*.txt"], "Load", [], ".", _X),
file::existFile(FName),
!,
Str= file::readString(FName, _IsUnicodeFile), editorControl_ctl:pasteStr(1, Str).
onLoadClick(_Source) = button::defaultAction().
Рисунок 17.6 Код для onLoad.
125

Глава 18: Печать
В предыдущей главе вы изучили, как построить текстовый редактор. В этой главе вы получите общее представление о печати.
•Создайте проект
Project Name: testPrt
UI Strategy: Object oriented GUI (pfc/GUI)
Target Type: Exe
Base Directory: C:\vip\codeForTyros
•Откомпилируйте приложение, для того, чтобы внести прототипы Task Window в дерево проекта.
•В дереве проекта, дважды щёлкните по ветке TaskMenu.mnu, и включите пункт &File/&New/tF7 из прототипа меню.
•В дереве проекта, щёлкните правой кнопкой мыши по TaskWindow.win, и выберите пункт Code Expert из контекстного меню, как на рис. 2.6. Появится Dialog and Window Expert. От кройте папки Menu, TaskMenu и id_file, как показано ниже.
Выберите ветку id_file_new и нажмите кнопку Add. Затем, дважды щёлкните по свежесозданной ветке id_file_new→on_file_new; наконец, замените прототип onFileNew(_Source, _MenuTag) фрагмен том, данным ниже.
clauses
onFileNew(_Source, _MenuTag) : PW=vpi::printStartJob("Recoreco"),
_HRES = vpi::winGetAttrVal(PW,attr_printer_hres), VRES = vpi::winGetAttrVal(PW,attr_printer_vres), V_SCR_RES=vpi::winGetAttrVal(PW,attr_screen_vres),
FNT=vpi::fontCreate(ff_Fixed,[], VRES*40 div V_SCR_RES), vpi::winSetFont(PW,FNT),
vpi::printStartPage(PW),
vpi::drawText(PW, 100, 200, "Before the sunset!"), vpi::printEndPage(PW),
vpi::printEndJob(PW).
Красота схемы печати Visual Prolog в том, что вы имеете дело с принтером, как если бы он был обычным графическим окном. Фактически, первое, что вы должны сделать, это открыть окно работы принтера.
PW=vpi::printStartJob("Recoreco")
Как только у вас будет окно, вы можете использовать его для получения информации о разреше нии принтера.
_HRES= vpi::winGetAttrVal(PW,attr_printer_hres), VRES= vpi::winGetAttrVal(PW,attr_printer_vres), V_SCR_RES=vpi::winGetAttrVal(PW,attr_screen_vres),
126

Методом проб и ошибок, а также пользуясь информацией о разрешении принтера, вы можете определить шрифт, который хорошо выглядит при печати.
FNT=vpi::fontCreate(ff_Fixed,[], VRES*40 div V_SCR_RES), vpi::winSetFont(PW,FNT),
Наконец, вы можете использовать любой предикат рисования и получить в итоге неплохо отпе чатанную страницу.
vpi::drawText(PW, 100, 200, "Before the sunset!"),
127

Глава 19:Формы с закладками
идругие полезности
•Создайте новый проект:
Name: tab_example
UI Strategy: Object GUI
•New in New Package: Создайте пакет под названием forms
•File/Add из каталога установки:
pfc\gui\controls\tabControl\tabControl.pack
•New in Existing Package (forms): Создайте Control – элемент управления – под названи ем hello_tab; чтобы выполнить это, выберите вариант Control на панели слева. Пере именуйте кнопку в button:yourname_ctl.
•Постройте приложение, для того, чтобы вставить код для событий. Добавьте следую щий фрагмент к ClickResponder кнопки button:yourname_ctl:
clauses
onYournameClick(_Source) = button::defaultAction : Name= edit_ctl:getText(),
Ans= string::concat("Hello, ", Name, "!\n"), stdio::write(Ans).
19.1.Знаменитыепрограммы
Существуют две программы, которые можно назвать имеющими дурную репутацию: “Hello, World!” и рекурсивное нахождение чисел Фибоначчи. В этой главе вы узнаете, как поместить обе эти
программы на элемент управления с закладками. Вы уже создали форму для хранения приложения hello. Давайте теперь создадим форму для последовательности Фибоначчи.
•New in Existing Package (forms): Control под названием fibTab; переименуйте кнопку в button:fib_ctl.
•Постройте приложение чтобы вставить код для событий. Добавьте следующий фрагмент к ClickResponder кнопки button:fib_ctl:
class predicates
fibo:(integer, integer) procedure (i, o). clauses
128

fibo(N, F) :
if N<2 then F=1 else
fibo(N 1, F1), fibo(N 2, F2), F= F1+F2
end if. predicates
onFibClick : button::clickResponder. clauses
onFibClick(_Source) = button::defaultAction : Num= edit_ctl:getText(),
I= toTerm(Num), fibo(I, F),
Ans= string::format("fibo(%d)= %d", I, F), edit_ctl:setText(Ans).
Ещё раз постройте приложение, чтобы убедиться, что всё работает как надо.
•Создайте новую форму в существующем пакете (нужный существующий пакет называется forms) под названием forms/tabs. Используйте кнопку с ключом Йале, для того, чтобы вставить tabControl на форму. Постройте приложение.
•Перейдите в файл tabs.pro, до которого можно добраться, щёлкнув по соответствующей ветке дерева проекта, и замените предложение
clauses new(Parent):
formWindow::new(Parent), generatedInitialize().
следующим фрагментом:
clauses new(Parent):
formWindow::new(Parent),
generatedInitialize(),
%
Page1 = tabPage::new(),
Tab1 = helloTab::new(Page1:getContainerControl()), Page1:setText(Tab1:getText()), tabControl_ctl:addPage(Page1),
Page2 = tabPage::new(),
Tab2 = fibTab::new(Page2:getContainerControl()), Page2:setText(Tab2:getText()),
129

tabControl_ctl:addPage(Page2), succeed.
•Включите пункт File/New меню приложения.
•Добавьте фрагмент
clauses
onFileNew(S, _MenuTag) :
W= tabs::new(S), W:show().
к TaskWindow.win/CodeExpert/Menu/TaskMenu/id_file/id_file_new.
•Постройте приложение в последний раз. Мило, не правда ли?
130