Как выйти из ситуации?
Есть процедура:
Код: Выделить всё
!==============================================================
MEMBER('reports_year.clw') ! Это модуль типа MEMBER
ReportVBLExcel PROCEDURE (Year1, Month1, Year2, Month2, NRep) ! Объявление процедуры
FilesOpened LONG
strPathRep CSTRING('C:\ABON_PR\REPORTS\')
window WINDOW('Идет формирование отчета...'),AT(,,419,93),FONT('MS Sans Serif',8,,),CENTER,GRAY
OLE,AT(4,4,26,24),USE(?OLE),HIDE
BUTTON('Отмена!'),AT(177,75,45,14),USE(?ButBreak)
END
END
!====================================
CODE ! Начало исполняемого кода
OPEN(window)
ACCEPT
IF EVENT()=EVENT:OpenWindow
?OLE{PROP:Create} = 'Excel.Application'
<=======Skipped=========>
! создается отчет
<=======Skipped=========>
RUN ('"' & ?OLE{'Application.Path'} & '\excel.exe" "' & FullName & '"')
BREAK
END !if openwindow
END !accept
RETURN
!==============================================================
Как мне обработать нажатие на кнопку для того чтобы прервать процесс формирования отчета?
Если отлавливать просто по
IF ACCEPTED() = ?ButBreak THEN
BREAK.
то при формирвоании отчета просто не удается нажать на эту кнопку.
Оно и понятно - у приложения (это все SDI - обычные окна без потоков и обычный Source(ШВС, C55EE(H))) нет времени обрабатывать очередь сообщений.
В C++Builder все решалось использованием функции ProcessMessages() которая заставляла приложения обработать все сообщения, что ему предназначааются.
А как быть в Clarion?
СПАСИБО
--
Best regards,
Иван mailto:shkmail@inbox.ru
(Добавление)
не просто нет времени, а твой код не получает управления, пока работает что-там-из-RUN-вызвалось.Оно и понятно - у приложения (это все SDI - обычные окна без потоков и обычный Source(ШВС, C55EE(H))) нет времени обрабатывать очередь сообщений.
если надо RUN-ить, то есть предложение стартонуть отдельный поток (если ниже cw6, то руками апишный), опционально сделать ему SetThreadPriority поменьше, а в твоем accept-цикле ловить нажатия на кнопки и прибивать этот поток ежели на кнопку нажали.
--
Best regards,
Maxim Yemelyanov,
Enigma Soft Company
phone: +380 572 177977
WEB: http://enigmasoft.com.ua
e-mail: clalist@enigmasoft.com.ua
ICQ: 12253836
Спасибо за ответ, но все "проще"
RUN тут не при чем. Основные действия выполняются между
IF EVENT()=EVENT:OpenWindow
и
END !if openwindow
Но все равно Спасибо!
--
Best regards,
Иван
(Добавление)
Насколько я понял, возможность прерывания необходима именно в коде "! создается отчет"?
Если так, то есть два варианта:
- переработать код таким образом, что-бы процесс формирования отчета производился, например, по типу шаблона Report/Process.
- использовать классы типа моего BasicProcessType, который должен лежать на одном из общедоступных Кларион-серверов. При этом вся модификация кода сводится к вставке нескольких доп. строк кода:
Код: Выделить всё
MyProcess BasicProcessType
ProcessBreak BYTE
...
MyProcess.Init(...)
ProcessBreak = False
ИШ> <=======Skipped=========>
Loop ! Цикл создания отчета
if ~MyProcess.LoopStep()
ProcessBreak = True
End
ИШ> ! создается отчет
End
ИШ> <=======Skipped=========>
MyProcess.Kill()
if ~ProcessBreak
ИШ> RUN ('"' & ?OLE{'Application.Path'} & '\excel.exe" "' & FullName & '"')
End
Вообщем, я думаю понятно в чем причина?
Код создания отчета должен обязательно "проходить"
через ACCEPT-цикл? что-бы иметь возможность получать сообщения, которые и порождаются нажатием на кнопки и буттоны.
=============================
С уважением, Олег А. Руденко.
Oleg_Rudenko@mail.ru
Oleg_Rudenko@mail333.com
Библиотека DynaLib
http://dynalib.narod.ru
То есть в простейшем случае будет что-то вроде этого?
Код: Выделить всё
!======================================================
i# = 0
OPEN(window)
ACCEPT
IF EVENT()=EVENT:OpenWindow
i# = 1
?OLE{PROP:Create} = 'Excel.Application'
END !if openwindow
IF i# = N
RUN ....
BREAK
END
IF i# > 0 AND i# < N
! создается строка отчета
! для текущего значения i#
! ...
i#++
END
END !accept
RETURN
!======================================================
--С уважением, Олег А. Руденко.
Взаимно ,
Иван
Нет. И что тут собственно изменилось по сравнению с начальным вариантом?
В C55 существует единственный способ прервать некий процесс, это установка таймера на окно. В этом случае, на событие
EVENT:Timer выполняются несколько итераций цикла формирования отчета. ACCEPT цикл снова прокручивается для обработки
всех возникших событий (нажатий на кнопки) и снова обрабытывает новое событие EVENT:Timer, выполняя следующие несколько
итераций.
Самое важное в этом деле - это подобрать правильное количество итераций, выполняемое на один тик таймера. Можно экспериментально, а можно и автоматизировать процесс.
Тут присутствуют всего два параметра.
TimerVal - величина PROP:Timer, по сути, это время отклика программы на итерактивное управление;
LoopVal - количество итераций одной обработки EVENT:Timer.
Таким образом, для оптимизации времени формирования отчета, следует максимально сократить простой ACCEPT цикла в период
формирования отчета, то есть минимизировать разницу времени TimerVal и времени исполнения одной порции итераций LoopVal.
Стоит оговориться, что установка заведомо большего количества LoopVal, чем может выполниться за TimeVal, приводит к
замедлению обработки и замедлению реакции на пользователя, это установлено экспериментально.
Ну так вот, рулить можно нашими двумя параметрами TimerVal и LoopVal.
Ниже пример как рулить подбором LoopVal, если рулить обоими пораметрами, то несколько сложнее.
Код: Выделить всё
TimerVal LONG(100)
LoopVal LONG(1)
ClockCount LONG
FlagProc BYTE(TRUE) ! Можно ли формировать отчет
MyWin WINDOW(...),..., TIMER(TimerVal)
...
END
CODE
OPEN(MyWin)
ACCEPT
CASE EVENT()
...
<обработка разных событий, в том числе нажатие на кнопку, если нужно остановить формирование отчета, то FlagProc
= FALSE>
...
OF EVENT:Timer
IF FlagProc
! Сохраняем время для расчета длительности выполнения LoopVal
ClockCount = CLOCK()
! Выполняем порцию итераций
LOOP LoopVal TIMES
...
<обработка очередной итерации>
...
IF <все данные отчета обработаны>
FlagProc = FALSE
END
WHILE FlagProc
! Расчет количества LoopVal
IF FlagProc
ClockCount = CLOCK() - ClockCount
IF ClockCount > TimerVal
IF LoopVal > 1 THEN LoopVal -= 1.
ELSE
LoopVal += INT((TimerVal - ClockCount) / (ClockCount / LoopVal))
END
END
END
...
END
END
CLOSE(MyWin)
__________________________________
Владимир Якимченко (IСQ 16 993 194)
(Добавление)
Именно так!
Будет, но медленно. Для ускорения последний IF кода можно "покрутить" немного в цикле, раз так 10-30.Будет работать. интересно?
Конечно, если создание одной строки отчета трудоемкая операция и занимает некоторое время, то в цикле такой код крутить не стоит.
=============================
С уважением, Олег А. Руденко
Здравствуйте, Иван!
Есть очень простой способ сделать это, не выходя за рамки Кларион
Дело в том, что команды Accept могут быть вложены одна в другую
Конструкция
Код: Выделить всё
0{Prop:Timer}=1
Accept
Break
End
0{Prop:Timer}=0
If Event()=Event:Accepted And Field()=?Cancel ... Then ....
В принципе, здесь происходит процесс ожидания 0.01 секунды, поэтому стоит проверять не на каждой записи, а, например, на каждой сотой. Или через 1-2 секунды работы...
---------------------------------------
C уважением,
Юрий Философов,
Главный программист
Корпорация "Диполь", Саратов
E-mail yufil@tacis-dipol.ru (служ)
yufil@mail.ru (дом)
ICQ#75924439
Код: Выделить всё
> ИШ> !======================================================
EVET:LoopAgain EQUATE(Evetn:User)
> ИШ> i# = 0
> ИШ> OPEN(window)
> ИШ> ACCEPT
> ИШ> IF EVENT()=EVENT:OpenWindow
> ИШ> i# = 1
> ИШ> ?OLE{PROP:Create} = 'Excel.Application'
Post(EVET:LoopAgain)
> ИШ> END !if openwindow
IF EVENT()=Post(EVET:LoopAgain)
> ИШ> IF i# = N
> ИШ> RUN ....
> ИШ> BREAK
! Лучше Post(Evetn:CloseWindow)
> ИШ> END
> ИШ> IF i# > 0 AND i# < N
> ИШ> ! создается строка отчета
> ИШ> ! для текущего значения i#
> ИШ> ! ...
> ИШ> i#++
Post(EVET:LoopAgain)
Cycle
> ИШ> END
END ! IF EVENT()=Post(EVET:LoopAgain)
> ИШ> END !accept
> ИШ> RETURN
> ИШ> !======================================================
"Летают. Ну, о-очень низенько."Бeет, но медленно.
Не будет. Событий для повторного входа в тело ACCEPT не будет. Надо либо аймер на окошко вешать, либо свой эвент себе любимому посылать. См. ополнения в коде ^
WBR, Nick Tsigouro
Написал: ClaList(2)