При программировании одной из штучек я столкнулся с проблемой получения значения, введенного в текстовое поле. Изучение доступной литературы ничего не дало, также как и обращение к одному из разработчиков – и тогда я немного приуныл.
Но… Через пару дней совершенно случайно у меня родилась идея как это можно немного подкорректировать. Идея в общем-то проста: поскольку в Icon существуют достаточно богатые возможности для отрисовки разных графических элементов (в том числе, и прямоугольников различных размеров и окраски) и средства захвата позиции курсора, находящегося в окне, то почему бы не сымитировать ввод в текстовое поле?
И тут нам потребуются те же геометрические познания, что были использованы при создании игр на Icon (“горячо-холодно”, “фие”), а именно, определение факта попадания курсора (при щелчке правой или левой кнопки мыши) в некоторую прямоугольную область.
Но сначала нужно нарисовать текстовое поле для чего используется следующая процедура:
procedure text_field(x,y,w,h)
Fg("gray")
DrawRectangle(x,y,w,h)
Fg("white")
DrawRectangle(x+2,y+2,w-4,h-4)
Fg("black")
end
рисующая два прямоугольника (разных цветов) один внутри другого и принимающая аргументы: x,y – координаты размещения левого верхнего угла текстового поля, w – ширина текстового поля, h – высота текстового поля.
Поле нарисовано, а теперь с помощью где-то выше упомянутых геометрических познаний перехватим курсор мыши, попавший в текстовое поле и установим позицию вывода строки (т.е. введенного в поле текста) прямо внутрь отрисованного текстового поля, а для получения значения текстового поля введем локальную переменную text, которая будет возвращена после того, как пользователь закончит ввод в текстовое поле.
Код процедуры:
procedure text_enter(x,y,w,h)
local text
repeat {
case Event() of {
&lpress|&rpress : {
if x<=&x<=(x+w) & y<=&y<=(y+h) then {
GotoXY(x+4,(y+h)-4)
text:=WRead()
GotoXY(0,0)
return text
}
}
}
}
end
процедура принимает те же аргументы, что и предыдущая.
А теперь небольшая ложка дегтя: значение переменной text будет возвращено только после нажатия Enter!
Ну а теперь процедура в рабочем демо-примере, в качестве которого была выбрана задача на определение счастливого билета.
Известно, что билет счастливый в том случае, если сумма цифр из первой половины номера равна сумме цифр второй половины номера билета. Это условие можно записать с помощью следующих двух процедур:
procedure sum(s)
local i,r
r:=0
every i:=1 to (*s) do {
r+:=s[i]
}
return r
end
procedure lucky(x)
local a
a:=(*x)/2
if sum(x[1+:a])=sum(x[(a+1):(*a)+1]) then return "Yes" else return "No"
end
Процедура sum принимает строку из цифр и вычисляет сумму для всей строки, а процедура lucky принимает строку с номером билета и сравнивая суммы первой половины строки с номером и второй строки с номером билета, выдает результат "Yes" или "No", в зависимости от того совпали суммы или нет.
Далее нам потребуется vib: сохранив все процедуры в отдельном файле, запускаем vib и создаем в нем новый файл, устанавливаем размеры окна 200*100 и помещаем на форму кнопку, сохраняем файл и закрываем vib.
Теперь нам vib не понадобиться и будем файл править вручную: в конце файла (или в начале) после фразы #===<>=== ищем вот такое описание ["button1:Button:regular::155,40,35,20:push",button_cb1] и исправляем значения: button1 заменяем на ?, push на ?.
Далее исправляем координаты, стоящие после слова regular, на вот такие значения - 155,40 (если у вас другие стоят, конечно) и переходим к процедуре button_cb1, которую заменяем на следующий код:
procedure button_cb1(vidget, value)
case vidget.id of {
"?" : Notice(lucky(v))
}
end
После этих плясков с бубном вставляем после процедуры button_cb1 процедуры отрисовки текстового поля и определения "счастливости" билета, а затем в процедуру main перед установкой переменной paused в 1 ставим следующий код:
DrawString(10,25,"Number of bilet:") text_field(130,10,60,20) v:=text_enter(130,10,60,20)
а перед самой процедурой main определяем глобальную переменную v, в которой сохраниться результат, введенный в текстовое поле. И все.
[accordion][panel intro="Под спойлером полный код для гурманов."]
############################################################################
#
# File: bilet.icn
#
# Subject: Program to ...
#
# Author:
#
# Date: July 29, 2012
#
############################################################################
#
#
#
############################################################################
#
# Requires:
#
############################################################################
#
# Links: vsetup
#
############################################################################
# This vib interface specification is a working program that responds
# to vidget events by printing messages. Use a text editor to replace
# this skeletal program with your own code. Retain the vib section at
# the end and use vib to make any changes to the interface.
link vsetup
global v
procedure main(args)
local vidgets, root, paused
(WOpen ! ui_atts()) | stop("can't open window")
vidgets := ui() # set up vidgets
root := vidgets["root"]
DrawString(10,25,"Number of bilet:")
text_field(130,10,60,20)
v:=text_enter(130,10,60,20)
paused := 1 # flag no work to do
repeat {
# handle any events that are available, or
# wait for events if there is no other work to do
while (*Pending() > 0) | \paused do {
ProcessEvent(root, QuitCheck)
}
# if is set null, code can be added here
# to perform useful work between checks for input
}
end
procedure button_cb1(vidget, value)
case vidget.id of {
"?" : Notice(lucky(v))
}
end
procedure text_field(x,y,w,h)
Fg("gray")
DrawRectangle(x,y,w,h)
Fg("white")
DrawRectangle(x+2,y+2,w-4,h-4)
Fg("black")
end
procedure text_enter(x,y,w,h)
local text
repeat {
case Event() of {
&lpress|&rpress : {
if x<=&x<=(x+w) & y<=&y<=(y+h) then {
GotoXY(x+4,(y+h)-4)
text:=WRead()
GotoXY(0,0)
return text
}
}
}
}
end
procedure sum(s)
local i,r
r:=0
every i:=1 to (*s) do {
r+:=s[i]
}
return r
end
procedure lucky(x)
local a
a:=(*x)/2
if sum(x[1+:a])=sum(x[(a+1):(*a)+1]) then return "Yes" else return "No"
end
#===<>=== modify using vib; do not remove this marker line
procedure ui_atts()
return ["size=200,100", "bg=pale gray"]
end
procedure ui(win, cbk)
return vsetup(win, cbk,
[":Sizer:::0,0,200,200:",],
["?:Button:regular::155,40,35,20:?",button_cb1],
)
end
#===<>=== end of section maintained by vib
[/panel][/accordion]

