среда, 7 января 2009 г.

Правильный порядок отключения и включения окон

Это перевод The correct order for disabling and enabling windows. Автор: Реймонд Чен.

Если вы хотите показать UI модально, вам нужно отключить (disable) владельца (owner window в терминах WinAPI) и включить (enable) модальное дочернее окно, плюс сделать всё наоборот, когда модальное окно закрывается (*).

И если вы что-то сделаете неправильно, то клавиатурный фокус будет вытворять странные вещи.

Когда вы закрываете модальный диалог, вы, скорее всего, захотите выполнить очистку в таком порядке:
  • Уничтожить модальный диалог.
  • Включить заново владельца.
Но если вы сделаете так, вы увидите, что окно владельца не активируется. Вместо этого, активируется какое-то совершенно случайное окно. Явная установка активности "исправляет" проблему, но у вас получается мерцание и порча Z-порядка окон.

Что же происходит?

Когда вы уничтожаете модальное окно - вы уничтожаете окно, которое сейчас активно. Поэтому менеджеру окон нужно кому-то передать фокус. Он пытается передать активацию владельцу вашего модального окна, но ведь владелец всё ещё отключён, поэтому менеджер окон пропускает его и ищет кого-то ещё - кого-то, кто ещё не отключён.

Именно поэтому у вас появляется непонятное активное окно.

Правильный порядок действий при уничтожении окна:
  • Включить владельца.
  • Уничтожить модальное окно.
На этот раз, когда модальное окно будет уничтожено, менеджер окон посмотрит на владельца и, эй, он увидит, что тот доступен - поэтому он передаст активность владельцу. Никакого мерцания. Никакого перекрытия другими окнами.

Примечание переводчика:
(*) Речь идёт о той же схеме, что использует Delphi: вместо использования модальных окон в терминах системы, программист эмулирует модальность, вручную запрещая все прочие окна.

4 комментария:

  1. На мой взгляд несколько сбивает с толку слово "владелец". Прочитав оригинал статьи Чена, я понял, что речь идет об окне - владельце (owner) нового окна. И второе, сразу возникает вопрос, а разве модальное открытие окна не делает окно, из которого это новое было открыто, неактивным? Чен в комментарии поясняет, что он описывает случай, когда программист сам явно управляет модальностью, не такой например, как вызов функции MessageBox.

    Сергей О.

    ОтветитьУдалить
  2. >>>об окне - владельце (owner)
    можно еще больше уточнить: owner window

    ОтветитьУдалить
  3. Да, спасибо за замечание. Поправил.
    Я обычно вставляю в скобках оригинал написания, если перевод не слишком удачен и/или может запутать. Конкретно в этом посте я просмотрел. Видимо, в голове пост смешался с предыдущими переводами, и я подумал, что добавил пояснение, а на самом деле - нет.

    ОтветитьУдалить
  4. >>>(*) Речь идёт о той же схеме, что использует Delphi ...
    Скажите, а можно ли добиться, чтобы в приложении написанном на Delphi, при щелчке на "owner window" (когда открыто модальное окно), происходила такая же реакция, как и "в терминах системы"? (Тоесть помигивали заголовки и т.д.)

    ОтветитьУдалить

Можно использовать некоторые HTML-теги, например:

<b>Жирный</b>
<i>Курсив</i>
<a href="http://www.example.com/">Ссылка</a>

Вам необязательно регистрироваться для комментирования - для этого просто выберите из списка "Анонимный" (для анонимного комментария) или "Имя/URL" (для указания вашего имени и ссылки на сайт). Все прочие варианты потребуют от вас входа в вашу учётку (поддерживается OpenID).

Пожалуйста, по возможности используйте "Имя/URL" вместо "Анонимный". URL можно просто не указывать.

Ваше сообщение может быть помечено как спам спам-фильтром - не волнуйтесь, оно появится после проверки администратором.