При программировании одной из штучек я столкнулся с проблемой получения значения, введенного в текстовое поле. Изучение доступной литературы ничего не дало, также как и обращение к одному из разработчиков — и тогда я немного приуныл.
Но… Через пару дней совершенно случайно у меня родилась идея как это можно немного подкорректировать. Идея в общем-то проста: поскольку в 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]