Вклинится с клавиатуры в цикл

Clarion, Clarion 7

Модератор: Дед Пахом

Правила форума
При написании вопроса или обсуждении проблемы, не забывайте указывать версию Clarion который Вы используете.
А так же пользуйтесь спец. тегами при вставке исходников!!!
Ответить
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8033
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Вклинится с клавиатуры в цикл

Сообщение Игорь Столяров »

Привет всем !

Возможно этот вопрос когда-то возникал, но сейчас он снова потребовался ...
Есть непреодолимое желание вклинится c клавиатуры в выполнение цикла ....
Т.е. что-то вроде:

Loop i# = 1 to 999999
If KeyBoard()
Ask
If KeyCode() = ESCKEY then Message('Escape').
end
end

Вроде бы все понятно, а не работает ... :(
Делать через ACCEPT - не хочу, медленно, да и не совсем подходит по условию задачи ....

Есть ли в этом мире решение такого вопроса ?
Make Clarion Great Again ! 😎
AlesDales
Активист
Сообщения: 198
Зарегистрирован: 14 Июль 2005, 15:42

Re: Вклинится с клавиатуры в цикл

Сообщение AlesDales »

А как часто, дорогой товарищ, вам лично давали полезные советы на этом сайте ?
Просто интересно, а то я чуть оператор YIELD не посоветовал. 8)
в стране слепых правит одноглазый король (c) ...
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Вклинится с клавиатуры в цикл

Сообщение dsabitov »

А вот и полное решение Вашего вопроса - даже самому понравилось :)))
Кнопка "Cycle" запускает Ваш бесконечный цикл. Кнопка "Cancel" - останавливает выполнение цикла.

PROGRAM

OMIT('***')
* Created with Clarion 8.0
* User: dsabitov
* Date: 02.09.2011
* Time: 18:56
*
* To change this template use Tools | Options | Coding | Edit Standard Headers.
***

MAP
CycleProc PROCEDURE
END
INCLUDE('KEYCODES.CLW')
Counter ULONG(0)
StopExecution BYTE(0)
Window WINDOW('Caption'),AT(,,202,68),GRAY,SYSTEM,FONT('MS Sans Serif',8)
BUTTON('&Cycle'),AT(61,44,41,14),USE(?OkButton),DEFAULT
BUTTON('&Cancel'),AT(103,44,42,14),USE(?CancelButton)
STRING(''),AT(9,11,184,22),USE(?Counter),CENTER,FONT('Lucida Sans Unicod' & |
'e',20,,FONT:bold)
END
SavedThread LONG
MainThread LONG
EVENT:DisplayCounter EQUATE(401h)
CODE
OPEN(WINDOW)
ACCEPT
CASE FIELD()
OF ?OkButton
IF EVENT() = EVENT:Accepted THEN
DISABLE(?OkButton)
StopExecution = 0
MainThread = THREAD()
SavedThread = START(CycleProc,35000)
CYCLE
END
OF ?CancelButton
IF EVENT() = EVENT:Accepted THEN
StopExecution = 1
?Counter{PROP:Text} = Counter
ENABLE(?OkButton)
DISPLAY
CYCLE
END
END
IF EVENT() = EVENT:DisplayCounter THEN
?Counter{PROP:Text} = Counter
DISPLAY(?Counter)
END
END
CycleProc PROCEDURE
CODE
LOOP
Counter += 1
IF INT(Counter/10000)*10000 = Counter THEN
POST(EVENT:DisplayCounter,,MainThread)
END
IF StopExecution = 1 THEN BREAK.
END
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8033
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Re: Вклинится с клавиатуры в цикл

Сообщение Игорь Столяров »

Да, спасибо ... Решение через ACCEPT очевидно, я поэтому сразу в вопросе это отметил.
Но все-таки остается непонятным почему цикл блокирует опрос клавиатуры ... ?
Make Clarion Great Again ! 😎
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Вклинится с клавиатуры в цикл

Сообщение dsabitov »

Игорь.. дело здесь вовсе не в ACCEPT. В текущем THREAD любой непрерывный цикл блокирует функционал текущего окна - т.е. все Ваши кнопки, горячие клавиши и т.д. Обратите внимание, что процедура с бесконечным циклом запущена в ДРУГОМ THREAD с помощью функции START. Только так можно организовать практически мгновенное прекращение выполнения бесконечного цикла. Так делают и в C и в Delphi...
Аватара пользователя
Игорь Столяров
Ветеран движения
Сообщения: 8033
Зарегистрирован: 07 Июль 2005, 10:19
Откуда: г. Ростов-на-ДоМу
Благодарил (а): 28 раз
Поблагодарили: 96 раз

Re: Вклинится с клавиатуры в цикл

Сообщение Игорь Столяров »

Я все вижу. THREAD здесь абсолютно не причем, - можете посмотреть код любого отчета или процесса по шаблонам ABC с кнопками "Остановить" и "Продолжить".
"любой непрерывный цикл" ничего не блокирует. Внутри цикла можно выполнять любые команды, в т.ч. и управления интерфейсом.
Проблема только в том, что кларионовская функция KeyBoard() не делает то, что должна - т.е. не видит момента нажатия на клавиатуре (или наличия данных в буфере ввода с клавиатуры). Есть серьезные опасения, что это очередная особенность реализации и просто нужно смотреть аналог в WinAPI .... или как это парадоксально звучит - воспользоваться советом и эксперементировать с комбинацией KeyBoard() + Yield.
Make Clarion Great Again ! 😎
dsabitov
Посетитель
Сообщения: 44
Зарегистрирован: 02 Апрель 2011, 12:30

Re: Вклинится с клавиатуры в цикл

Сообщение dsabitov »

Судя по описанию:
...Within your Clarion application, YIELD only allows control to pass to EVENT:Timer events in other execution threads. This allows you to code a "background" procedure in its own execution thread using the TIMER attribute to perform some long batch processing without requiring the user to wait until the task is complete before continuing with other work in the application. This is an industry-standard Windows method of doing background processing within an application...
YIELD делает примерно тоже самое, что было предложено выше.
Аватара пользователя
Губин Игорь
Шубуршун
Сообщения: 2584
Зарегистрирован: 16 Сентябрь 2005, 16:35
Откуда: Москва
Благодарил (а): 3 раза
Поблагодарили: 26 раз

Re: Вклинится с клавиатуры в цикл

Сообщение Губин Игорь »

Воскури мануал!

Дело в том, что ASK удаляет из буфера 1 символ, а KeyCode возвращает код текущего символа в буфере. Т.е. у тебя получается, что KeyCode всегда вернёт отсутствие символа, т.к. его уже "проглотил" ASK. Это превосходно видно на примере из HELPа (очистка буфера клавиатуры):

ASK !ждём ввода символов
LOOP WHILE KEYBOARD() !Если какой-то символ есть в буфере
ASK ! глотаем символ из буфера
END

Т.е. цикл толжен выглядеть так

Код: Выделить всё

Loop i# = 1 to 999999

   Yield ! Просто так, чтобы дать возможность системе поработать

   LOOP WHILE KEYBOARD() !Если что-то есть в буфере
     If KeyCode() = ESCKEY then ! если это ESC выводим сообщение
       Message('Escape')
     End
     Ask ! "снимаем" символ из буфера 
   end ! уходим на проверку наличия символов
   
End
Это я только кажусь дураком! На самом деле я полный идиот!
Ответить