Я попробовал добавить в диалог элемент, который может получать фокус (конкретно - кнопку). Но, как выяснилось, диалог не получает событий от мыши и клавиатуры, пока не закончится цикл. Более того! ФАР, похоже, не получает прерываний (как если бы цикл выполнялся в главном потоке). А как организовать "фоновое"выполнение цикла? Надо делать coroutine и т.д.?
Посмотрите, пожалуйста, слегка усложненный диалог. Всё бы хорошо, но пока цикл не кончится, он ни на что не реагирует
ifnot cont thenbreakend-- BAX, проверка, надо ли снимать цикл
win.Sleep(500)
hDlg:send("DM_SETTEXT",2,i)
end
if cont then hDlg:send("DM_CLOSE")end-- BAX закрытие диалога по окончании цикла, если он сам не закрылся
просто если диалог нужен только для отображения информации, то вполне достаточно было бы использовать far.Text (например, в процедуре копирования файлов я именно так и выводил прогресс)
Немодальный диалог
Posted: Tue 06 Nov, 2018 09:19
by John Doe
buniak_a_h, вы неправильно тестируете, и соответственно делаете преждевременные выводы.
Для начала стоит посмотреть вызывается ли обработчик, и с какими параметрами.
Для этого удобно использовать win.OutputDebugString.
P.S.
Но я и сам кое-что не понял: почему-то первые 15 раз обработчик вызывается с закрытым дескриптором в качестве первого параметра: FarDialog (closed).
John Doe wrote: ↑Tue 06 Nov, 2018 09:19buniak_a_h, вы неправильно тестируете, и соответственно делаете преждевременные выводы.
Для начала стоит посмотреть вызывается ли обработчик, и с какими параметрами.
Для этого удобно использовать win.OutputDebugString.
1. Обработчик вызывается. Проверено в немодальном варианте
2. Можно в списке аргументов указать трижды _,, но на работу это не повлияет - проверено в другом скрипте.
3. Просто уберите обработчик и попробуйте переключиться на другое окно (Ctrl+Tab). Пока цикл не закончится, у Вас это не получится.
local function DlgProc(hDlg,Msg,Param1,Param2) -- JD: правильные аргументы
if Msg==F.DN_CLOSE then cont=false end -- BAX, при закрытии диалога выставляю признак, что цикл можно снимать
end
return far.DialogInit(id,-1,-1,len,4,len,items,flags, DlgProc)
end
local hDlg = Progress(" ")
local i = 1
far.Timer(500,function(t)
i = i+1
if not cont or i>20 then t:Close(); return end
hDlg:send("DM_SETTEXT",2,i)
end)
Немодальный диалог
Posted: Tue 06 Nov, 2018 14:18
by buniak_a_h
John Doe wrote: ↑Tue 06 Nov, 2018 13:59В нём тоже:
Вы пробовали?
1. До окончания цикла DN_BTNCLICK не приходит обработчику
2. Добавление "правильных" параметров не исправляет ситуацию
3. Можете обработчик просто убрать - даже в этом случае управление ФАР не получит. Ни на другое окно не переключиться, ни диалог закрыть.
John Doe wrote: ↑Tue 06 Nov, 2018 13:59
А цикл в отдельном потоке, по ACTL_SYNCHRO:
Спасибо, попробую...
А где можно почитать про классы? В мануале по LeaFar написано:
У timer object-а, видимо, должен быть метод типа Free() ? Ведь надо как-то его останавливать после закрывания диалога...
В мануале упомянут timer:Close(), но это не ответ. Хотелось бы описание типа с перечислением доступных методов и пропертей...
Немодальный диалог
Posted: Tue 06 Nov, 2018 14:26
by John Doe
buniak_a_h wrote: ↑Tue 06 Nov, 2018 14:18
Вы пробовали?
Разумеется.
Замените ваш код моим и всё.
buniak_a_h wrote: ↑Tue 06 Nov, 2018 14:18
В мануале упомянут timer:Close(), но это не ответ. Хотелось бы описание типа с перечислением доступных методов и пропертей...
В мануале всё есть.
Немодальный диалог
Posted: Tue 06 Nov, 2018 14:31
by John Doe
John Doe wrote: ↑Tue 06 Nov, 2018 14:26
Замените ваш код моим и всё.
Поправка: этого достаточно для демонстрации, что желаемое вами достижимо, но не гарантирую, что код полный.
Немодальный диалог
Posted: Tue 06 Nov, 2018 14:37
by buniak_a_h
John Doe wrote: ↑Tue 06 Nov, 2018 14:26
buniak_a_h писал(а): ↑Вт 06 ноя, 2018 16:18
Вы пробовали?
Разумеется.
Замените ваш код моим и всё.
Заменил. (обработчик, не far.Timer!) Есессно, ничего не заработало.
Если ФАР висит без обработчика, то исправление ошибок в нём на результат не влияет. Чудес не бывает...
Немодальный диалог
Posted: Tue 06 Nov, 2018 14:42
by John Doe
John Doe wrote: ↑Tue 06 Nov, 2018 13:59
А цикл в отдельном потоке, по ACTL_SYNCHRO:
Из этого разве не следует что вы должны заменить и свой цикл моим таймером?
local id = win.Uuid"45B09D0D-6AE8-416C-BB5A-F5FA7B5CC430"
local F = far.Flags
local timer
local function Progress(text,title)
local len = math.max(10,text:len()+2)
local items = {
--[[01]] {F.DI_SINGLEBOX,0,0,len,4,0,0,0,0,title},
--[[02]] {F.DI_TEXT, 1,1,0,0,0,0,0,F.DIF_CENTERGROUP,text},
--[[03]] {F.DI_BUTTON, -1,2,-1,2,0,0,0,F.DIF_CENTERGROUP,"Ok"},
}
local flags = F.FDLG_NONMODAL
return far.DialogInit(id,-1,-1,len,4,len,items,flags,function(hDlg,Msg)
if Msg==F.DN_CLOSE then timer:Close() end
end)
end
local hDlg = Progress(" ")
local i = 0
timer = far.Timer(500,function(t)
i = i+1
if i>20 then t:Close(); return end
hDlg:send(F.DM_SETTEXT,2,i)
end)
Немодальный диалог
Posted: Tue 06 Nov, 2018 17:17
by buniak_a_h
John Doe wrote: ↑Tue 06 Nov, 2018 14:42
з этого разве не следует что вы должны заменить свой цикл моим таймером?
Я же про обработчик писал, что он не влияет. А что таймер поможет - я просто тогда не пробовал.
Теперь попробовал. работает, спасибо.