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

Содержание

  1. Порядок создания немодального диалога
  2. Процесс обслуживания немодального диалога
  3. Фоновые вызовы процедуры обслуживания
  4. Немодальный диалог в объектной модели видеосистемы

Порядок создания немодального диалога

Немодальный диалог в отличие от модального допускает переключение на другие немодальные окна клиента ASB (мышью или клавишами Num+ и Num*). Поддержан в версии 14.263.110 на основе класса DIALOG.

Немодальный диалог следует создавать так.

Для вызова процедуры обслуживания немодального диалога используется тот же механизм, что и для выполнения опции CALL из меню, поэтому процедура обслуживания должна быть размещена в головном модуле. Назначение процедуры обслуживания - обрабатывать события диалога и его элементов управления, т.е. вызывать DIALOG.Wait, и, при необходимости, перерисовывать диалог по таймауту. Процедура обслуживания должна выглядеть приблизительно так.

PROCEDURE OnProcessUserInput(dlg: DIALOG);
BEGIN
 IF dlg.Active THEN
  WHILE dlg.Visible & ~dlg.ExternalUserInputReceived DO
   (* обновление вида диалога *)
   dlg.Wait(10);  (* 10 секунд - условно *)
  END;
 ELSE
  dlg.Wait(0);  (* для фонового вызова DIALOG.OnSize вследствие изменения размеров главного окна *)
 END;
END {OnProcessUserInput};

Цикл, в котором вызывается DIALOG.Wait, очень похож на тот, что пишется для модального диалога. Разница в дополнительной проверке флагового свойства DIALOG.ExternalUserInputReceived. Поднятый флаг означает, что в очереди ввода присутствует событие, не относящееся к немодальному диалогу, например Num+ для переключения на следующее открытое окно, или клик в пустое место главного окна для поднятия главного меню, или Alt+F9 для выбора набора палитр, или NTF-программа при помощи LIKEMENU поместила опции в очередь команд. Если флаг поднят, процедура обслуживания должна завершиться, чтобы дать системе обработать событие.

Флаговое свойство DIALOG.Active поднято, когда окно немодального диалога активно. Пока "активное окно" можно понимать как верхнее, точное определение будет приведено в следующем разделе. Ветка ~DIALOG.Active написана для вызова обработчика DIALOG.OnSize (изнутри DIALOG.Wait) для неактивного окна немодального диалога вследствие изменения размеров главного окна. Такой вызов поддержан начиная с версии 14.263.130.

Если перерисовывать диалог не нужно, не нужен и цикл; процедуру обслуживания можно упростить до приведенного ниже вида.

PROCEDURE OnProcessUserInput(dlg: DIALOG);
BEGIN
 IF dlg.Active THEN
  dlg.Wait();
 ELSE
  dlg.Wait(0);
 END;
END {OnProcessUserInput};

А если учесть, что для неактивного немодального диалога метод DIALOG.Wait возвращает управление без ожидания, процедура обслуживания будет выглядеть еще короче.

PROCEDURE OnProcessUserInput(dlg: DIALOG);
BEGIN
 dlg.Wait();
END {OnProcessUserInput};

Нетривиальный момент: нажатие Esc не только прерывает три вышеприведенных варианта процедуры обслуживания, но и скрывает немодальный диалог. Дело в том, что в случае неудачного завершения процедуры обслуживания (необработанное исключение) диалог скрывается автоматически. А нажатие Esc в диалоге именно выбрасывает исключение 301 класса Exc_TermByUser.

Процесс обслуживания немодального диалога

По завершении программного комплекса, сделавшего видимым немодальный диалог(и), будет автоматически создан(ы) процесс(ы) обслуживания немодального диалога, подобный процессам Edit, View, ShowWin, Survey и т.п.

Процесс обслуживания немодального диалога в цикле выполняет следующее.

Теперь можно уточнить понятие активного немодального диалога. Немодальный диалог является активным, пока его процесс обслуживания является верхним процессом, исключая промежутки времени, когда поднято меню, или открыто немодальное сообщение/форма, дочернее к немодальному диалогу.

Вызов процедуры обслуживания отличается рядом особенностей.

Фоновые вызовы процедуры обслуживания

Если необходимо регулярно обновлять вид неактивного немодального диалога, программист может включить фоновые вызовы процедуры обслуживания по таймеру. Свойство DIALOG.InactiveTimeout задает интервал в секундах между фоновыми вызовами. По умолчанию свойство содержит пустое значение, т.е. фоновых вызовов нет. Если свойство непусто - процедура будет вызываться, но не чаще одного раза в 2.5 секунды.

Подобно NTF-программам фоновый вызов процедуры обслуживания происходит в случайный момент, в том числе во время работы другой программы. Соответственно, для него действуют почти те же ограничения, что и для NTF-программ.

С учетом фоновых вызовов процедура обслуживания должна выглядеть так.

PROCEDURE OnProcessUserInput(dlg: DIALOG);
BEGIN
 IF dlg.Active THEN  (* диалог активен *)
  WHILE dlg.Visible & ~dlg.ExternalUserInputReceived DO
   (* обновление вида диалога *)
   dlg.Wait(10);  (* 10 секунд - условно *)
  END;
 ELSE  (* фоновый вызов *)
 (* обновление вида диалога *)
 dlg.Wait(0);
END;
END {OnProcessUserInput};

Немодальный диалог в объектной модели видеосистемы

В объектной модели видеосистемы немодальному диалогу соответствует тип окна WINDOW.Type_ModelessDialog и класс окна MODELESS_DIALOG_WINDOW. Экземпляр MODELESS_DIALOG_WINDOW может присутствовать в коллекции APP.VisibleWindows, также на него может ссылаться свойство APP.TopWindow. Свойство WINDOW.Id можно использовать для активации немодального диалога опцией GoToWin. Свойства WINDOW.Width и WINDOW.Depth (размеры окна в знакоместах) для немодального диалога не имеют смысла и возвращают 0.