среда, 24 февраля 2010 г.

Опасности фильтрования сообщений

Это перевод The dangers of filtering window messages. Автор: Реймонд Чен.

Функции GetMessage и PeekMessage позволяют вам указать фильтр, ограничивающий обрабатываемые сообщения по описателю окна или диапазону кодов сообщений, которые функции будут получать из очереди. Хотя это вполне нормально - использовать их, но вы только убедитесь, что время от времени вы позволяете проходить любому (нефильтрованному) сообщению.

Частой ошибкой бывает использование GetMessage с фильтром по окну в вашем цикле выборки сообщений:
  while GetMessage(Msg, Wnd, 0, 0) do // Неверно!
begin
TranslateMessage(Msg);
DispatchMessage(Msg);
end;
Хотя ваша программа может создавать всего одно окно, этот код, тем не менее, неверен.

"Как это может быть?" - спросите вы, - "Моя программа имеет только одно окно. Почему тут могут быть какие-то ещё сообщения для других окон? Фильтр, хотя и избыточен, но ведь безвреден, правда?"

Многие системные службы создают окна для вас. Например, если включено редактирование метода ввода, то редактор метода может создать вспомогательные окна для содействия вводу символов. Если вы инициализируете COM, то тогда COM может решить создать вспомогательное окно для поддержки межпоточного маршаллинга. Если вы используете только фильтрованный GetMessage, то сообщения для этих окон никогда не будут обработаны, а вы останетесь сидеть и почёсывать голову, соображая, почему ваша программа иногда зависает, когда вы, например, пытаетесь сделать drag&drop.

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

1 комментарий:

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

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

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

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

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