View Issue Details

IDProjectCategoryView StatusLast Update
0002587Far ManagerPlugins API.Dialogpublic2014-03-19 13:18
ReporterJohnDoe Assigned To 
PrioritynormalSeverityminorReproducibilityalways
Status newResolutionopen 
Product Version3.0 
Summary0002587: В момент первого DN_GOTFOCUS неверно работают функции AdvControl
DescriptionПосле открытия диалога активируется первый фокусный элемент и посылается сообщение DN_GOTFOCUS.
Если в этот момент обработчик события воспользуется функциями ACTL_REDRAWALL, ACTL_GETWINDOWINFO, ACTL_GETWINDOWTYPE, то их результат будет неожиданным.

Этой проблемы нет с последующими DN_GOTFOCUS
Steps To Reproducelocal F = far.Flags
Event { group="DialogEvent";
  condition=function(Event,param)
    return Event==2 and param.Msg==F.DN_GOTFOCUS
  end;
  action=function(Event,param)
    far.AdvControl (F.ACTL_REDRAWALL)
    local TypeName = far.AdvControl (F.ACTL_GETWINDOWINFO).TypeName
    local Type = far.AdvControl (F.ACTL_GETWINDOWTYPE).Type
    far.Text(1,0,1,TypeName)
    far.Text(1,1,1,Type)
  end;
}

После установки данного обработчика необходимо открыть диалог, например диалог копирования (F5).
Видно, что панели исчезли (проблема с ACTL_REDRAWALL), и в левом верхнем углу отображается текст Panels.

После нажатия Tab всё нормализуется.
Additional InformationНе уверен что это связано, но в момент первого DN_GOTFOCUS также неверно работают функции макроязыка, например Area.Current, Menu.Id, Dialog.Id

После второго DN_GOTFOCUS всё нормализуется
TagsNo tags attached.
Build

Activities

JohnDoe

2014-01-30 12:13

updater   bugnote:0011801

http://api.farmanager.com/ru/dialogapi/dmsg/dn_gotfocus.html
Сказано: "Событие также приходит для фокусного элемента сразу после DN_INITDIALOG."
Значит первый DN_GOTFOCUS приходит до того как диалог отрисован, от этого и проблемы.

Поскольку "раннее" появление DN_GOTFOCUS упоминается в документации, то описываемая проблема строго говоря не является багом.

Вероятно стоит переместить в проект "Wishes"

vskirdin

2014-03-13 07:42

administrator   bugnote:0011906

Вижу два пути:

1. вынести посыл DN_GOTFOCUS из инициализации диалога поближе к отрисовке
2. для первого DN_GOTFOCUS в Param2 указать не 0, а скажем, -1 (по своей сути первый DN_GOTFOCUS - это всё еще этап инциализации диалога)

Второй вариант более разумный ибо для первого варианта возможны интересные визуальные эффекты ;-)

zg

2014-03-13 08:29

developer   bugnote:0011910

в чём разумность второго варианта, если он по сути ничего не меняет?

vskirdin

2014-03-13 08:36

administrator   bugnote:0011911

Внимательно прочти

zg

2014-03-13 08:47

developer   bugnote:0011912

я прочитал. первый DN_GOTFOCUS можно отследить и сейчас.

JohnDoe

2014-03-13 11:56

updater   bugnote:0011914

Для чего вообще первый DN_GOTFOCUS приходит так рано?
Может быть всё можно решить посылая ещё один DN_GOTFOCUS после того как диалог отрисуется?

>первый DN_GOTFOCUS можно отследить и сейчас.
Какой способ рекомендуется?

vskirdin

2014-03-13 13:25

administrator   bugnote:0011916

Возможно первый DN_GOTFOCUS неудачно назван. Задача этого сообщения указать диалоговой процедуре где будет клавиатурный фокус ввода после того, как запустится основной цикл взаимодействия с юзером.

Плагин, при передаче "массива контролов" в Far, может указать флаг DIF_FOCUS на элементе не имеющего отношения к "клавиатурному фокусу" (или вообще не указывать этот флаг). Это как бы не ошибка, но пользователю будет не комфортно.

В процессе инициализации элементов диалога Far прослеживает этот факт (и то, что нет элементов с таким флагом) и корректирует значение "фокуса" на "следующий" ближайший допустимый элемент. После этого сообщает диалоговой процедуре "истинное" значение индекса элемента с фокусом (который может совпадать с тем, что передал плагин, если плагин не наврал).

JohnDoe

2014-03-13 13:42

updater   bugnote:0011917

Возможно ли корректировать значение фокуса ещё на этапе DN_INITDIALOG?

Если нет, то что если посылать ещё один DN_GOTFOCUS после отрисовки?

И о каких интересных визуальных эффектах речь выше 0002587:0011906?

vskirdin

2014-03-13 14:19

administrator   bugnote:0011919

> Возможно ли корректировать значение фокуса ещё на этапе DN_INITDIALOG?
Это и так делается при инициализации. Событие DN_GOTFOCUS это информационный сигнал свершившегося факта.

> Если нет, то что если посылать ещё один DN_GOTFOCUS после отрисовки?
Не перебор? :-) (hint: отрисовка достаточно часто происходит)

> И о каких интересных визуальных эффектах речь выше?
Я пытаюсь всего лишь предположить ;-)

JohnDoe

2014-03-13 14:30

updater   bugnote:0011921

>Это и так делается при инициализации.
Я о DN_INITDIALOG/Param1: "ID элемента, который получит фокус ввода по умолчанию."
"По умолчанию" здесь на основании данных переданных плагином, или уже скорректированное значение?

>Не перебор? :-) (hint: отрисовка достаточно часто происходит)
Я имел ввиду после отрисовки диалога, но однократно.

vskirdin

2014-03-13 15:43

administrator   bugnote:0011923

> Я о DN_INITDIALOG/Param1:
Зачем?
В передаваемом массиве элементов это уже есть в виде флага DIF_FOCUS.

Сегодня у тебя в диалоге "рамка" и "строка редактирования", ты ставишь Param1 равный 1 (если от нуля считать). Потом понимаешь, что неплохо обозначить что это за строка редактирования и ставишь перед ней "метку" (индекс строки редактирования сместился), но забываешь скорректировать Param1...

JohnDoe

2014-03-13 15:56

updater   bugnote:0011924

Это понятно.
Возможно я не совсем понимаю как это работает, но выше сказано:

> DN_GOTFOCUS ... Задача этого сообщения указать диалоговой процедуре где будет клавиатурный фокус ввода ...

В связи с этим вопрос: та самая диалоговая процедура о которой говорится в цитате ведь получает DN_INITDIALOG после завершения инициализации? Почему тогда DN_INITDIALOG не может выполнить указанную задачу?

vskirdin

2014-03-13 17:26

administrator   bugnote:0011926

Понял.

Ок. Смотрим как это работает:

1. Элементы проинициализированы (в т.ч. вычислен "истинный" индекс фокусного элемента)
2. Far отсылает DN_INITDIALOG в функцию-обработчик диалога, передавая в Param1-"вычисленный" ID фокусного элемента.
3. В случае, если диалоговая функция изменили данные (вернула в Far значение TRUE), то Far переинициализирует данные с учетом "сейчасных" изменений (в т.ч. перерасчитывает индекс фокусного элемента, т.к. "есть подозрение, что плагин поменял фокусный элемент при обработке DN_INITDIALOG"). После этой вторичной реинициализации повторно DN_INITDIALOG не посылается.
4. Независимо от наличия п.3 идет посыл DN_GOTFOCUS с "новым" индексом фокусного элемента.

Если отправку DN_GOTFOCUS делать _только_ для случая, если процедура-обработчик в ответ на DN_INITDIALOG вернула TRUE, то не получим ли мы ситуацию, когда некий плагин (написанный с учетом Писания) всегда ждёт DN_GOTFOCUS сразу после DN_INITDIALOG, а тут бац - а он не пришел и плагин сломался.

Я всё таки склоняюсь к тому, чтобы "первый" DN_GOTFOCUS (который относится к инициации) в Param2 содержал что-то, отличное от нуля.
1. Поломки из-за отсутствия DN_GOTFOCUS нет (пред.абзац)
2. Функция-обработчик всегда знает (без собственных вычислений этого факта), что для варианта DN_GOTFOCUS(Param2=-1) лишних движений с отрисовкой не делать, а ждать...

JohnDoe

2014-03-13 19:49

updater   bugnote:0011927

>"первый" DN_GOTFOCUS (который относится к инициации)
В своём скрипте я хочу по DN_GOTFOCUS выполнять определённые действия для которых необходимо чтобы диалог уже был отрисован.

Всё бы ничего, но первый DN_GOTFOCUS приходит слишком рано.
Предлагаемый вами Param2 позволит легко отфильтровать первый DN_GOTFOCUS, но это не решит проблему. Потому что в таком случае при открытии диалога мой скрипт вообще не сработает.

Вижу такие варианты
- Посылать первый DN_GOTFOCUS после отрисовки (я так понял это не получится)
- Сразу после отрисовки посылать ещё один DN_GOTFOCUS.

>Возможно первый DN_GOTFOCUS неудачно назван
Да, когда-нибудь при очередной ломке стоит завести для него отдельное сообщение.

vskirdin

2014-03-18 10:25

administrator   bugnote:0011959

А для чего указанный скрипт?

JohnDoe

2014-03-18 10:30

updater   bugnote:0011960

http://forum.farmanager.com/viewtopic.php?f=60&t=8463
Изначально задумывался для автоматической активации фильтра в меню, листбоксах, комбобоксах.
(на данный момент DN_GOTFOCUS не используется, ввиду описанных проблем)

vskirdin

2014-03-18 10:41

administrator   bugnote:0011961

В общем тут нашел багу (??)
Вместо DN_GOTFOCUS подставил DN_DRAWDIALOGDONE и получил переполнение стека - процедура отрисовки диалога зацикливалась (при срабатывании вызова диалога и заюзывания этого скрипта).
Зацикливание убрал, но "far.AdvControl (F.ACTL_REDRAWALL)" дает непрорисовку диалога вообще (правда работают, но тихо :-)).
Закомментировал строку - проблемы этого тикета исчезли.
На тестирование - https://dl.dropboxusercontent.com/u/13020996/far/m2587.7z

JohnDoe

2014-03-18 12:45

updater   bugnote:0011967

Last edited: 2014-03-18 12:46

>Зацикливание убрал
Правильно ли это? Вроде логично чтобы после ACTL_REDRAWALL приходило сообщение DN_DRAWDIALOGDONE

>Вместо DN_GOTFOCUS подставил DN_DRAWDIALOGDONE
Правильно ли я понимаю, что вместо DN_GOTFOCUS предлагается использовать DN_DRAWDIALOGDONE?

Мне не кажется это хорошей идеей, и я даже не знаю всех случаев когда DN_DRAWDIALOGDONE может приходить.
Например во всех меню оно приходит самопроизвольно (как DN_ENTERIDLE)

vskirdin

2014-03-19 06:48

administrator   bugnote:0011972

>>Зацикливание убрал
>Правильно ли это?
Это юмор такой?

> Вроде логично чтобы после ACTL_REDRAWALL приходило сообщение DN_DRAWDIALOGDONE
Оно и придет, но только не в момент отрисовки диалога. Отлови идле-событие и дай команду ACTL_REDRAWALL.
Зацикливание было по причине, что скрипт запускал ACTL_REDRAWALL в момент, когда отрисовка диалога еще не закончилась.


>>Вместо DN_GOTFOCUS подставил DN_DRAWDIALOGDONE
>Правильно ли я понимаю, что вместо DN_GOTFOCUS предлагается использовать DN_DRAWDIALOGDONE?
Как вариант.

Функция отрисовки вызывается достаточно часто: изменилось состояние элемента - вызывается функция отрисовки для ЭТОГО элемента. DN_DRAWDIALOGDONE при этом общий (отрисовка и для всего диалога так и для отрисовки конкретного элемента)

> Мне не кажется это хорошей идеей, и я даже не знаю всех случаев когда DN_DRAWDIALOGDONE может приходить.
Хмм..

Так, вроде неточность есть в АПИ.
а) Отрисовка всего диалога:
1. DN_DRAWDIALOG
2. DN_CTLCOLORDIALOG
3. N раз {
    DN_DRAWDLGITEM
    DN_CTLCOLORDLGITEM
}
4. DN_DRAWDIALOGDONE

б) Отрисовка элемента:
3. N раз {
    DN_DRAWDLGITEM
    DN_CTLCOLORDLGITEM
}
4. DN_DRAWDIALOGDONE

Т.е. для элемента нет DN_DRAWDIALOG, парной для DN_DRAWDIALOGDONE.
В писании сказано, что "Сообщение DN_DRAWDIALOGDONE посылается после прорисовкой всего диалога". Т.е. такое событие не должно приходить для элемента.

Как вариант - DN_DRAWDIALOG так же посылать для отрисовки элемента, передавая в Param1 ID отрисовываемого элемента. Только в этом случае что делать с индексом. Сейчас Param1 всегда = 0.

JohnDoe

2014-03-19 08:17

updater   bugnote:0011976

Last edited: 2014-03-19 08:18

>DN_DRAWDIALOGDONE [...] Т.е. такое событие не должно приходить для элемента.
Вероятно здесь логично было бы иметь отдельное событие DN_DRAWDLGITEMDONE.
Ломать поздно? (хотя не знаю какой плагин это вообще мог использовать)

>Как вариант - DN_DRAWDIALOG так же посылать для отрисовки элемента[...]
Для элемента уже есть DN_DRAWDLGITEM, зачем его дублировать. Проще передавать ID в DN_DRAWDIALOGDONE

...
Возвращаясь к теме: почему не сделать как я предлагал выше: 0002587:0011927

vskirdin

2014-03-19 10:58

administrator   bugnote:0011979

> почему не сделать как я предлагал выше
Потому, что не логично DN_GOTFOCUS использовать иначе как "такой то элемент получил фокус ввода". Событие должно приходить "вовремя и к месту".
Я не вижу смысла переносить первый DN_GOTFOCUS сразу после отрисовки ("ближе к прорисовке" - он уже и так присылается сразу после инитдиалога и перед прорисовкой).

В принципе можно первый DN_GOTFOCUS вообще убрать, чтобы не вводил в заблуждение. Если плагин захочет узнать у кого фокус - кинет месаг DM_GETFOCUS.

Вопрос. Ты планируешь использовать весь функционал, даже если в этот момент он не к месту (например, "в DN_INITDIALOG что-то рисовать, вместо того, чтобы инциализировать элементы")?

JohnDoe

2014-03-19 11:56

updater   bugnote:0011980

>Я не вижу смысла переносить первый DN_GOTFOCUS сразу после отрисовки
Как же смысла не видишь, когда это и есть суть тикета, заявленная ещё в описании.

Сейчас первый DN_GOTFOCUS приходит ДО отрисовки диалога, и поэтому я нормальным образом не могу ничего сделать.

>например, "в DN_INITDIALOG что-то рисовать, вместо того, чтобы инциализировать элементы"
Вообще-то об этом 0002616, и нет, я как раз хочу делать "к месту", но места такого нет.
(Рисовать не надо было, в том примере задача была прочитать заголовок окна, который в тот момент ещё недоступен. А в другом примере - воспользоваться фильтром меню, который опять же не доступен)

vskirdin

2014-03-19 12:48

administrator   bugnote:0011981

Last edited: 2014-03-19 12:50

> Сейчас первый DN_GOTFOCUS приходит ДО отрисовки диалога, и поэтому я нормальным образом не могу ничего сделать.
Это означает, что удаляем первый DN_GOTFOCUS?

> Рисовать не надо было, в том примере задача была прочитать заголовок окна,...
Значит DN_DRAWDIALOGDONE с установкой внутреннего флага, что ты уже получил данные.

Второй вариант: добавить новый месаг DM_GETDIALOGTITLE (который тебе вернет строку, используемую ФАРом для выставления заголовка диалога) и использовать его в DN_INITDIALOG.
Делать?

> А в другом примере - воспользоваться фильтром меню, который опять же не доступен
Как воспользоваться? Очистить? Заполнить? Отобразить? Что именно? Разжовывай на пальцах.

Если в скриптах юзается плагиновое АПИ, то видимо и поступать надо так, как будто плагин пишешь :-)

JohnDoe

2014-03-19 12:53

updater   bugnote:0011982

Last edited: 2014-03-19 13:18

>Это означает, что удаляем первый DN_GOTFOCUS?
Я хочу получать DN_GOTFOCUS при активации первого элемента диалога, но после отрисовки (чтобы не было никакой разницы между первым и последующими DN_GOTFOCUS)

По остальному ответил в соседнем тикете: 0002616:0011983

Issue History

Date Modified Username Field Change
2014-01-29 21:52 JohnDoe New Issue
2014-01-30 12:13 JohnDoe Note Added: 0011801
2014-03-13 07:42 vskirdin Note Added: 0011906
2014-03-13 08:29 zg Note Added: 0011910
2014-03-13 08:36 vskirdin Note Added: 0011911
2014-03-13 08:47 zg Note Added: 0011912
2014-03-13 11:56 JohnDoe Note Added: 0011914
2014-03-13 13:25 vskirdin Note Added: 0011916
2014-03-13 13:42 JohnDoe Note Added: 0011917
2014-03-13 14:19 vskirdin Note Added: 0011919
2014-03-13 14:30 JohnDoe Note Added: 0011921
2014-03-13 15:43 vskirdin Note Added: 0011923
2014-03-13 15:56 JohnDoe Note Added: 0011924
2014-03-13 17:26 vskirdin Note Added: 0011926
2014-03-13 19:49 JohnDoe Note Added: 0011927
2014-03-18 10:25 vskirdin Note Added: 0011959
2014-03-18 10:30 JohnDoe Note Added: 0011960
2014-03-18 10:41 vskirdin Note Added: 0011961
2014-03-18 12:45 JohnDoe Note Added: 0011967
2014-03-18 12:46 JohnDoe Note Edited: 0011967
2014-03-19 06:48 vskirdin Note Added: 0011972
2014-03-19 08:17 JohnDoe Note Added: 0011976
2014-03-19 08:18 JohnDoe Note Edited: 0011976
2014-03-19 10:58 vskirdin Note Added: 0011979
2014-03-19 11:56 JohnDoe Note Added: 0011980
2014-03-19 12:48 vskirdin Note Added: 0011981
2014-03-19 12:50 vskirdin Note Edited: 0011981
2014-03-19 12:53 JohnDoe Note Added: 0011982
2014-03-19 13:18 JohnDoe Note Edited: 0011982