понедельник, 25 октября 2010 г.

Вынос окна на передний план - это как любовь: вы не можете её украсть, вам её должны подарить

Это перевод Foreground activation permission is like love: You can't steal it, it has to be given to you. Автор: Реймонд Чен.

Когда кто-то запускает вторую копию вашего приложения, которое допускает только один экземпляр, вы обычно хотите, чтобы вторая копия послала первой командную строку (и как-то разобралась бы с текущим каталогом), а затем вы хотите, чтобы первая копия вылезла на передний план. Но при этом люди часто встречаются с проблемой, что если вызовете в первом экземпляре SetForegroundWindow, она завершится неудачей.

Проблема тут в том, что с точки зрения менеджера окон первый экземпляр программы получил какое-то сообщение и неожиданно попытался украсть передний план. Это сообщение не было сообщением ввода, поэтому оконный менеджер не видит никаких причин, которые давали бы вашей первой копии права на передний фон. У него нет доказательств, что первая копия выходит на передний план, отвечая на действие пользователя.

Есть несколько способов разобраться с этой проблемой. Проще всего - пусть вторая копия вызывает SetForegroundWindow. У второй программы есть на это право, потому что её только что запустил пользователь. И если программа забрала себе передний план, то она также может его и отдать - в нашем случае, передачей его окну первой программе.

Второй способ сделать это - пусть вторая программа вызовет функцию AllowSetForegroundWindow, указав PID первой программы прежде чем отправлять ей сообщение. Функция AllowSetForegroundWindow даёт возможность программе сказать менеджеру окон: "Всё в порядке, он со мной". А когда затем первый экземпляр попробует выдвинуть себя на передний план вызовом SetForegroundWindow, менеджер окон скажет: "Ага, с ним нет проблем. Другая программа поручилась за него".

Если вы передаёте право на передний план COM серверу, то вы можете использовать соответствующую COM функцию CoAllowSetForegroundWindow.

Во всех случаях заметьте, что вы не можете отдать что-то, что вам не принадлежит. Если у вас нет права на передний план, то вызов AllowSetForegroundWindow (или её эквивалентов) ничего не сделает: вы говорите менеджеру окон: "Всё в порядке, он со мной", а он вам отвечает: "Ты кто, чёрт побери, такой?".

Упреждающий сварливый комментарий: "А всё же существует очень хитрый способ обойти правило и украсть передний план". Ага, а ещё находятся очень хитрые люди, которые находят способ украсть любовь. Если с миром всё в порядке, то обе группы людей рано или поздно себя обнаружат и будут страдать за свои злодеяния.

Обновление: удалил все комментарии, показывающие способы обойти правила. Ну вы даёте.

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

  1. Ахахахахаа статья - огонь))) Поржал)))
    Спасибо)

    ОтветитьУдалить
  2. > Обновление: удалил все комментарии, показывающие способы обойти правила. Ну вы даёте.

    Лол. :D

    ОтветитьУдалить
  3. В принципе, я согласен, что «левые» окна не должны выскакивать наверх и мешать.

    Но есть и исключения. К примеру, программа рабочего места оператора. Эта программа должна иметь приоритет над другими. И, как минимум, окно авторизации должно быть постоянно на виду. Можно, конечно, сказать, что нужно запускать в «монопольном» режиме, чтобы никого больше не было. Но, к сожалению, не все заказчики на это согласны. Они желают и программу видеть наверху (хотя бы её первое окно — авторизации), и иметь возможность работать с другими программами. А «заказчик всегда прав» ((. Вот и приходится изобретать методы обхода.

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

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

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

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

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

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