Page 5 of 6

Немодальный диалог

Posted: Mon 21 May, 2018 17:22
by John Doe

Latest post of the previous page:

@2useven10

Code: Select all

zg 17.10.2014 04:06:40 +0200 - build 4138

1. ACTL_GETWINDOWINFO возвращает все окна в порядке текущего z-order'а.
Текущее окно имеет максимальный индекс, окно под ним на единицу меньше.

Не документировано, но пока так.

Немодальный диалог

Posted: Mon 21 May, 2018 18:36
by 2useven10
Т.е. фактически actl(SETCURRENTWINDOW, actl(GETWINDOWCOUNT) - 2)
Вроде работает, но хотелось бы всё-таки сертифицированный способ...

Немодальный диалог

Posted: Mon 21 May, 2018 20:40
by zg
а чем этот несертифицированный?

Немодальный диалог

Posted: Mon 21 May, 2018 21:00
by 2useven10
Тем что такой порядок окон упоминается только в changelog.

Немодальный диалог

Posted: Tue 06 Nov, 2018 08:15
by buniak_a_h
John Doe wrote: Sat 30 Sep, 2017 09:24 Сомневаюсь что должно.

Code: Select all

--здесь был Ваш пример
Тут то же самое, без DM_REDRAW не отображается.
Я попробовал добавить в диалог элемент, который может получать фокус (конкретно - кнопку). Но, как выяснилось, диалог не получает событий от мыши и клавиатуры, пока не закончится цикл. Более того! ФАР, похоже, не получает прерываний (как если бы цикл выполнялся в главном потоке). А как организовать "фоновое"выполнение цикла? Надо делать coroutine и т.д.?
Посмотрите, пожалуйста, слегка усложненный диалог. Всё бы хорошо, но пока цикл не кончится, он ни на что не реагирует

просто если диалог нужен только для отображения информации, то вполне достаточно было бы использовать far.Text (например, в процедуре копирования файлов я именно так и выводил прогресс)

Немодальный диалог

Posted: Tue 06 Nov, 2018 09:19
by John Doe
buniak_a_h, вы неправильно тестируете, и соответственно делаете преждевременные выводы.
Для начала стоит посмотреть вызывается ли обработчик, и с какими параметрами.
Для этого удобно использовать win.OutputDebugString.

В конкретном данном случае вы ошиблись с параметрами функции-обработчика, должно быть так: https://api.farmanager.com/ru/defs/dlgproc.html

Немодальный диалог

Posted: Tue 06 Nov, 2018 09:25
by John Doe
P.S.
Но я и сам кое-что не понял: почему-то первые 15 раз обработчик вызывается с закрытым дескриптором в качестве первого параметра: FarDialog (closed).

https://bugs.farmanager.com/view.php?id=3669

Немодальный диалог

Posted: Tue 06 Nov, 2018 13:36
by buniak_a_h
John Doe wrote: Tue 06 Nov, 2018 09:19 buniak_a_h, вы неправильно тестируете, и соответственно делаете преждевременные выводы.
Для начала стоит посмотреть вызывается ли обработчик, и с какими параметрами.
Для этого удобно использовать win.OutputDebugString.

В конкретном данном случае вы ошиблись с параметрами функции-обработчика, должно быть так: https://api.farmanager.com/ru/defs/dlgproc.html
1. Обработчик вызывается. Проверено в немодальном варианте
2. Можно в списке аргументов указать трижды _,, но на работу это не повлияет - проверено в другом скрипте.
3. Просто уберите обработчик и попробуйте переключиться на другое окно (Ctrl+Tab). Пока цикл не закончится, у Вас это не получится.
  1. local id = win.Uuid"45B09D0D-6AE8-416C-BB5A-F5FA7B5CC430"
  2.  
  3. local F = far.Flags
  4.  
  5. local cont=true -- BAX - признак активности диалога
  6.  
  7. local function Progress(text,title)
  8.  
  9.   local len = math.max(10,text:len()+2)
  10.  
  11.   local items = {
  12.  
  13.     --[[01]]  {F.DI_SINGLEBOX,0,0,len,4,0,0,0,0,title},
  14.  
  15.     --[[02]]  {F.DI_TEXT,     1,1,0,0,0,0,0,"DIF_CENTERGROUP",text},
  16.  
  17.               {"DI_BUTTON", -1,2,-1,2,0,0,0,"DIF_CENTERGROUP",'Ok'} -- BAX, добавлена кнопка
  18.  
  19.   }
  20.  
  21.   local flags = F.FDLG_NONMODAL
  22.  
  23.   return far.DialogInit(id,-1,-1,len,4,len,items,flags)
  24.  
  25. end
  26.  
  27.  
  28.  
  29. local hDlg = Progress("  ")
  30.  
  31. for i=1,20 do
  32.  
  33.   --hDlg:send"DM_REDRAW"
  34.  
  35.   if not cont then break end -- BAX, проверка, надо ли снимать цикл
  36.  
  37.   win.Sleep(500)
  38.  
  39.   hDlg:send("DM_SETTEXT",2,i)
  40.  
  41. end
  42.  
  43. if cont then hDlg:send("DM_CLOSE") end -- BAX закрытие диалога по окончании цикла, если он сам не закрылся ACTL_SYNCHRO
Так что дело не в обработчике - 100%

Немодальный диалог

Posted: Tue 06 Nov, 2018 13:59
by John Doe
buniak_a_h wrote: Tue 06 Nov, 2018 13:36 Так что дело не в обработчике - 100%
В нём тоже:

Code: Select all

  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
А цикл в отдельном потоке, по ACTL_SYNCHRO:

Code: Select all

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 = far.Timer (interval, handler [, ...])
Returns:
timer : userdata (timer object), or nil
У timer object-а, видимо, должен быть метод типа Free() ? Ведь надо как-то его останавливать после закрывания диалога...

Немодальный диалог

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:
Из этого разве не следует что вы должны заменить и свой цикл моим таймером?

Update
Вот чуть причёсанный вариант:

Code: Select all

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 з этого разве не следует что вы должны заменить свой цикл моим таймером?
Я же про обработчик писал, что он не влияет. А что таймер поможет - я просто тогда не пробовал.
Теперь попробовал. работает, спасибо.