Сведения о сообщениях и очередях сообщений
В отличие от приложений на основе MS-DOS, приложения на основе Windows управляются событиями. Они не выполняют явные вызовы функций (например, вызовы библиотеки времени выполнения C) для получения входных данных. Вместо этого они ожидают передачи в систему входных данных.
Система передает все входные данные для приложения различным окнам в приложении. Каждое окно имеет функцию, называемую процедурой окна, которая вызывается системой всякий раз, когда она имеет входные данные для окна. Процедура окна обрабатывает входные данные и возвращает элемент управления в систему. Дополнительные сведения о процедурах окна см. в .
Если окно верхнего уровня перестает отвечать на сообщения в течение нескольких секунд, система считает, что окно не отвечает. В этом случае система скрывает окно и заменяет его фантомным окном с одинаковым порядком Z, расположением, размером и визуальными атрибутами. Это позволяет пользователю перемещать его, изменять размер или даже закрывать приложение. Однако это единственные действия, которые доступны, так как приложение на самом деле не отвечает. В режиме отладчика система не создает окно призрака.
В этом разделе рассматриваются следующие разделы:
- сообщения Windows
- Типы сообщений
- Маршрутизация сообщений
-
обработка сообщений
- цикл сообщений
- процедура окна
- фильтрация сообщений
- Публикация и отправка сообщений
- взаимоблокировки сообщений
- Трансляция сообщений
- запроса сообщений
Сообщения Windows
Система передает входные данные в процедуру окна в виде сообщения . Сообщения создаются системой и приложениями. Система создает сообщение при каждом входном событии, например, когда пользователь вводит, перемещает мышь или щелкает элемент управления, например полосу прокрутки. Система также создает сообщения в ответ на изменения в системе, вызванные приложением, например, когда приложение изменяет пул системных ресурсов шрифтов или изменяет размер одного из его окон. Приложение может создавать сообщения для направления собственных окон для выполнения задач или взаимодействия с окнами в других приложениях.
Система отправляет сообщение в оконную процедуру с набором из четырех параметров: дескриптор окна, идентификатор сообщения и два значения, которые называются параметры сообщения. Дескриптор окна определяет окно, для которого предназначено сообщение. Система использует это, чтобы определить, какая процедура окна должна принимать сообщение.
Идентификатор сообщения является именованной константой, определяющей назначение сообщения. Когда процедура окна получает сообщение, он использует идентификатор сообщения для определения способа обработки сообщения. Например, идентификатор сообщения WM_PAINT сообщает процедуре окна, что клиентская область окна изменилась и должна быть перерисована.
Параметры сообщения указывают данные или расположение данных, используемых процедурой окна при обработке сообщения. Значение и значение параметров сообщения зависят от сообщения. Параметр сообщения может содержать целое число, упакованные битовые флаги, указатель на структуру, содержащую дополнительные данные и т. д. Если сообщение не использует параметры сообщения, они обычно задаются для NULL. Процедура окна должна проверить идентификатор сообщения, чтобы определить, как интерпретировать параметры сообщения.
Типы сообщений
В этом разделе описаны два типа сообщений:
System-Defined Сообщения
Система отправляет или постит сообщение, определенное системой при обмене данными с приложением. Эти сообщения используются для управления операциями приложений и предоставления входных и других сведений для обработки приложений. Приложение также может отправлять или публиковать сообщения, определенные системой. Приложения обычно используют эти сообщения для управления операцией окон управления, созданных с помощью предварительно зарегистрированных классов окон.
Каждое системное сообщение имеет уникальный идентификатор сообщения и соответствующую символьную константу (определенную в файлах заголовков пакета SDK), которая указывает назначение сообщения. Например, константа WM_PAINT запрашивает у окна отображение его содержимого.
Символьные константы указывают категорию, к которой относятся системные сообщения. Префикс константы определяет тип окна, который может интерпретировать и обрабатывать сообщение. Ниже приведены префиксы и связанные с ними категории сообщений.
Общие сообщения окна охватывают широкий спектр информации и запросов, включая сообщения для ввода мыши и клавиатуры, ввода меню и диалогового окна, создания окна и управления и динамического обмена данными (DDE).
Сообщения Application-Defined
Приложение может создавать сообщения для использования собственными окнами или взаимодействовать с окнами в других процессах. Если приложение создает собственные сообщения, процедура окна, которая получает их, должна интерпретировать сообщения и предоставлять соответствующую обработку.
Значения идентификатора сообщения используются следующим образом:
- Система резервирует значения идентификатора сообщения в диапазоне 0x0000 через 0x03FF (значение WM_USER –1) для системных сообщений. Приложения не могут использовать эти значения для частных сообщений.
- Значения в диапазоне 0x0400 (значение WM_USER) через 0x7FFF доступны для идентификаторов сообщений для классов частного окна.
- Если приложение отмечено версией 4.0, можно использовать значения идентификатора сообщения в диапазоне 0x8000 (WM_APP) через 0xBFFF для частных сообщений.
- Система возвращает идентификатор сообщения в диапазоне 0xC000 через 0xFFFF, когда приложение вызывает функцию RegisterWindowMessage для регистрации сообщения. Идентификатор сообщения, возвращаемый этой функцией, гарантированно будет уникальным во всей системе. Использование этой функции предотвращает конфликты, которые могут возникнуть, если другие приложения используют один и тот же идентификатор сообщения для разных целей.
Маршрутизация сообщений
Система использует два метода для маршрутизации сообщений в процедуру окна: отправка сообщений в очередь первого входа, первого выхода, называемую очередью сообщений , которая является системным объектом памяти, временно сохраняющим сообщения, и отправка сообщений непосредственно в процедуру окна.
Сообщение, которое публикуется в очередь сообщений, называется поставленным в очередь. Это в первую очередь результат ввода пользователем с помощью мыши или клавиатуры, например, сообщения WM_MOUSEMOVE, WM_LBUTTONDOWN, WM_KEYDOWNи WM_CHAR. Другие сообщения в очереди включают таймер, краску и выход из сообщений: WM_TIMER, WM_PAINTи WM_QUIT. Большинство других сообщений, которые отправляются непосредственно в процедуру окна, называются непоставленные в очередь сообщения.
Сообщения в очереди
Система может отображать любое количество окон одновременно. Чтобы перенаправить ввод мыши и клавиатуры в соответствующее окно, система использует очереди сообщений.
Система поддерживает одну системную очередь сообщений и одну очередь сообщений для каждого потока графического интерфейса. Чтобы избежать затрат на создание очереди сообщений для потоков, отличных от графического интерфейса, все потоки создаются изначально без очереди сообщений. Система создает очередь сообщений для конкретного потока только при первом вызове одной из конкретных пользовательских функций. вызовы функции GUI не приводят к созданию очереди сообщений.
Когда пользователь перемещает мышь, нажимает кнопки мыши или типы на клавиатуре, драйвер устройства для мыши или клавиатуры преобразует входные данные в сообщения и помещает их в очередь системных сообщений. Система удаляет сообщения из очереди системных сообщений, проверяет их, чтобы определить целевое окно, а затем отправляет их в очередь сообщений потока, создавшего целевое окно. Очередь сообщений потока получает все сообщения мыши и клавиатуры для окон, созданных потоком. Поток удаляет сообщения из очереди и направляет систему для их отправки в соответствующую процедуру окна для обработки.
За исключением сообщения WM_PAINT, сообщения WM_TIMER и сообщения WM_QUIT система всегда публикует сообщения в конце очереди сообщений. Это гарантирует, что окно получает входные сообщения в правильной последовательности FIFO (первым пришёл, первым ушёл). Однако сообщение WM_PAINT, сообщение WM_TIMER и сообщение WM_QUIT хранятся в очереди и пересылаются в процедуру окна только в том случае, если очередь не содержит других сообщений. Кроме того, несколько WM_PAINT сообщений для одного окна объединяются в одно WM_PAINT сообщение, консолидируя все недопустимые части клиентской области в одну область. Объединение сообщений WM_PAINT уменьшает количество случаев, когда окно должно перерисовать содержимое клиентской области.
Система публикует сообщение в очередь сообщений потока, заполняя структуру MSG, а затем копируя её туда. Сведения в MSG включают в себя: дескриптор окна, для которого предназначено сообщение, идентификатор сообщения, два параметра сообщения, время публикации сообщения и положение курсора мыши. Поток может отправить сообщение в собственную очередь сообщений или в очередь другого потока с помощью функции PostMessage или PostThreadMessage.
Приложение может удалить сообщение из очереди с помощью функции GetMessage. Чтобы изучить сообщение без удаления из очереди, приложение может использовать функцию PeekMessage. Эта функция заполняет MSG сведениями о сообщении.
После удаления сообщения из очереди приложение может использовать функцию DispatchMessage, чтобы направить систему для отправки сообщения в процедуру окна для обработки. DispatchMessage принимает указатель на MSG, заполненный предыдущим вызовом функции GetMessage или PeekMessage. DispatchMessage передает дескриптор окна, идентификатор сообщения и два параметра сообщения процедуре окна, но не передает время, когда сообщение было отправлено, или положение курсора мыши. Приложение может получить эти сведения, вызвав GetMessageTime и функции GetMessagePos при обработке сообщения.
Поток может использовать функцию WaitMessage, чтобы обеспечить управление другими потоками, если в очереди сообщений нет сообщений. Функция приостанавливает поток и не возвращается, пока новое сообщение не будет помещено в очередь сообщений потока.
Можно вызвать функцию SetMessageExtraInfo, чтобы связать значение с очередью сообщений текущего потока. Затем вызовите функциюGetMessageExtraInfo, чтобы получить значение, связанное с последним сообщением, полученное функцией GetMessage или PeekMessage.
Непоставленные сообщения
Неочередные сообщения отправляются немедленно в процедуру целевого окна, обходя системную очередь сообщений и очередь сообщений потока. Система обычно отправляет неочередные сообщения, чтобы уведомить окно о событиях, влияющих на него. Например, когда пользователь активирует новое окно приложения, система отправляет окно ряд сообщений, включая WM_ACTIVATE, WM_SETFOCUSи WM_SETCURSOR. Эти сообщения уведомляют окно о том, что он был активирован, что ввод клавиатуры направляется в окно, и что курсор мыши был перемещен в границах окна. Непоставленные в очередь сообщения также могут результатировать в том, что приложение вызывает определенные системные функции. Например, система отправляет сообщение WM_WINDOWPOSCHANGED после того, как приложение использует функцию SetWindowPos для перемещения окна.
Некоторые функции, отправляющие несольные сообщения, включают BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeoutи SendNotifyMessage.
Обработка сообщений
Приложение должно удалять и обрабатывать сообщения, размещенные в очередях сообщений своих потоков. Однопоточное приложение обычно использует цикл сообщений в функции WinMain для удаления и отправки сообщений в соответствующие процедуры окна для обработки. Приложения с несколькими потоками могут включать цикл сообщений в каждом потоке, который создает окно. В следующих разделах описывается, как работает цикл сообщений и объясняется роль процедуры окна:
Цикл сообщений
Простой цикл сообщений состоит из одного вызова функции для каждой из этих трех функций: GetMessage, TranslateMessageи DispatchMessage. Обратите внимание, что при возникновении ошибки GetMessage возвращает значение –1, поэтому требуется специальное тестирование.
MSG msg;
BOOL bRet;
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (bRet == -1)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
Функция GetMessage извлекает сообщение из очереди и копирует его в структуру типа MSG. Он возвращает ненулевое значение, если он не встречает сообщение WM_QUIT, в этом случае возвращается FALSE и завершает цикл. В однопоточном приложении завершение цикла сообщений часто является первым шагом при закрытии приложения. Приложение может завершить свой собственный цикл с помощью функции PostQuitMessage, как правило, в ответ на сообщение WM_DESTROY в процедуре окна главного окна приложения.
Если указать дескриптор окна в качестве второго параметра GetMessage, из очереди извлекаются только сообщения для указанного окна. GetMessage также может фильтровать сообщения в очереди, извлекая только те сообщения, которые попадают в указанный диапазон. Дополнительные сведения о фильтрации сообщений см. в разделе Фильтрация сообщений.
Цикл сообщений потока должен содержать TranslateMessage, если поток должен получать входные данные символов с клавиатуры. Система создает сообщения виртуального ключа (WM_KEYDOWN и WM_KEYUP) каждый раз, когда пользователь нажимает клавишу. Сообщение виртуального ключа содержит код виртуального ключа, который определяет, какой ключ был нажат, но не его символьное значение. Чтобы получить это значение, цикл сообщений должен содержать TranslateMessage, который преобразует сообщение виртуального ключа в символьное сообщение (WM_CHAR) и помещает его обратно в очередь сообщений приложения. Затем символьное сообщение может быть удалено в ходе следующей итерации цикла сообщений и отправлено в оконную процедуру.
Функция DispatchMessage отправляет сообщение в процедуру окна, связанную с дескриптором окна, указанным в структуре MSG. Если дескриптор окна равен HWND_TOPMOST, то DispatchMessage отправляет сообщение в оконные процедуры всех окон верхнего уровня в системе. Если дескриптор окна NULL, DispatchMessage ничего не делает с сообщением.
Основной поток приложения запускает цикл сообщений после инициализации приложения и создания по крайней мере одного окна. После запуска цикл сообщений продолжает извлекать сообщения из очереди сообщений потока и отправлять их в соответствующие окна. Цикл сообщений заканчивается, когда функция GetMessage удаляет сообщение WM_QUIT из очереди сообщений.
Для очереди сообщений требуется только один цикл сообщений, даже если приложение содержит много окон. DispatchMessage всегда отправляет сообщение в соответствующее окно; Это связано с тем, что каждое сообщение в очереди представляет собой структуру MSG, содержащую дескриптор окна, к которому принадлежит сообщение.
Цикл сообщений можно изменить различными способами. Например, можно получить сообщения из очереди, не отправляя их в окно. Это полезно для приложений, которые отправляют сообщения, не указывая окно. Вы также можете направлять GetMessage для поиска определенных сообщений, оставляя другие сообщения в очереди. Это полезно, если необходимо временно обойти обычный порядок FIFO очереди сообщений.
Приложение, использующее клавиши акселератора, должно иметь возможность переводить сообщения клавиатуры в командные сообщения. Для этого цикл сообщений приложения должен включать вызов функции TranslateAccelerator. Дополнительные сведения о клавишах-ускорителях см. в Ускорители клавиатуры.
Если поток использует немодальное диалоговое окно, цикл сообщений должен включать функцию IsDialogMessage, чтобы диалоговое окно могло получать ввод с клавиатуры.
Процедура окна
Процедура окна — это функция, которая получает и обрабатывает все сообщения, отправленные в окно. Каждый класс окна имеет процедуру окна, и каждое окно, созданное с этим классом, использует ту же процедуру окна для реагирования на сообщения.
Система отправляет сообщение в оконную процедуру, передавая данные сообщения в качестве аргументов этой процедуры. Затем процедура окна выполняет соответствующее действие для сообщения; он проверяет идентификатор сообщения и при обработке сообщения использует сведения, указанные параметрами сообщения.
Процедура окна обычно не игнорирует сообщение. Если он не обрабатывает сообщение, он должен отправить сообщение обратно в систему для обработки по умолчанию. Процедура окна выполняет это путем вызова функции DefWindowProc, которая выполняет действие по умолчанию и возвращает результат сообщения. Затем процедура окна должна возвращать это значение в качестве собственного результата сообщения. Большинство процедур окон обрабатывают только несколько сообщений и передают другие в систему путем вызова DefWindowProc.
Поскольку процедура окна используется всеми окнами, принадлежащими одному классу, она может обрабатывать сообщения для нескольких разных окон. Чтобы идентифицировать конкретное окно, затронутое сообщением, оконная процедура может использовать дескриптор окна, переданный с сообщением. Для получения дополнительной информации о процедурах окна см. процедуры окна.
Фильтрация сообщений
Приложение может выбрать определенные сообщения для получения из очереди сообщений (игнорируя другие сообщения) с помощью функции GetMessage или PeekMessage, чтобы указать фильтр сообщений. Фильтр представляет собой диапазон идентификаторов сообщений (заданных первым и последним идентификатором), дескриптором окна или обоими. GetMessage и PeekMessage используют фильтр сообщений для выбора сообщений для получения из очереди. Фильтрация сообщений полезна, если приложение должно выполнять поиск в очереди сообщений для сообщений, которые прибыли позже в очередь. Также полезно, если приложение должно обрабатывать входные (аппаратные) сообщения перед обработкой опубликованных сообщений.
Константы WM_KEYFIRST и WM_KEYLAST можно использовать в качестве значений фильтра для получения всех сообщений клавиатуры; константы WM_MOUSEFIRST и WM_MOUSELAST можно использовать для получения всех сообщений мыши.
Любое приложение, которое фильтрует сообщения, должно гарантировать, что сообщение удовлетворяет фильтру сообщений. Например, если приложение фильтрует сообщение WM_CHAR в окне, которое не получает ввод клавиатуры, функция GetMessage не возвращается. Это фактически приводит к зависанию приложения.
Публикация и отправка сообщений
Любое приложение может публиковать и отправлять сообщения. Как и в системе, приложение отправляет сообщение, копируя его в очередь сообщений и отправляя сообщение путем передачи данных сообщения в качестве аргументов в процедуру окна. Для публикации сообщений приложение использует функцию PostMessage. Приложение может отправить сообщение, вызвав функцию SendMessage, BroadcastSystemMessage, SendMessageCallback, SendMessageTimeout, SendNotifyMessageили SendDlgItemMessage.
Публикация сообщений
Приложение обычно публикует сообщение, уведомляющее определенное окно о выполнении задачи. PostMessage создает структуру MSG для сообщения и копирует сообщение в очередь сообщений. Цикл сообщений приложения в конечном итоге извлекает сообщение и отправляет его в соответствующую процедуру окна.
Приложение может публиковать сообщение без указания окна. Если приложение предоставляет дескриптор окна NULL при вызове PostMessage, сообщение опубликовывается в очередь, связанную с текущим потоком. Так как дескриптор окна не указан, приложение должно обрабатывать сообщение в цикле сообщений. Это один из способов создать сообщение, которое применяется ко всему приложению, а не к конкретному окну.
Иногда может потребоваться опубликовать сообщение во всех окнах верхнего уровня в системе. Приложение может опубликовать сообщение во всех окнах верхнего уровня, вызвав PostMessage и указав HWND_TOPMOST в параметре hwnd.
Распространенная ошибка программирования заключается в том, что функция PostMessage всегда публикует сообщение. Это не так, если очередь сообщений заполнена. Приложение должно проверить возвращаемое значение функции PostMessage , чтобы определить, отправлено ли сообщение и, если оно не было, отправьте его заново.
Отправка сообщений
Приложение обычно отправляет сообщение, чтобы уведомить процедуру окна немедленно выполнить задачу. ФункцияSendMessageотправляет сообщение в процедуру окна, соответствующую заданному окну. Функция ожидает завершения обработки обработчика окна, а затем возвращает результат сообщения. Родительские и дочерние окна часто взаимодействуют, отправляя сообщения друг другу. Например, родительское окно с элементом управления правки в качестве дочернего окна может задать текст элемента управления, отправив в него сообщение. Элемент управления может уведомить родительское окно об изменениях текста, внесённых пользователем, отправляя сообщения родительскому окну.
Функция SendMessageCallback также отправляет сообщение в процедуру окна, соответствующую заданному окну. Однако эта функция возвращается немедленно. После обработки сообщения система вызывает указанную функцию обратного вызова. Дополнительные сведения о функции обратного вызова см. в функции SendAsyncProc.
Иногда может потребоваться отправить сообщение всем окнам верхнего уровня в системе. Например, если приложение изменяет системное время, оно должно уведомить все окна верхнего уровня об изменении, отправив сообщение WM_TIMECHANGE. Приложение может отправлять сообщение во все окна верхнего уровня, вызвав SendMessage и указав HWND_TOPMOST в параметре hwnd. Вы также можете транслировать сообщение всем приложениям, вызвав функцию BroadcastSystemMessage и указав BSM_APPLICATIONS в параметре lpdwRecipients.
Используя функцию InSendMessage или InSendMessageEx, процедура окна может определить, обрабатывает ли сообщение, отправленное другим потоком. Эта возможность полезна, если обработка сообщений зависит от источника сообщения.
Взаимоблокировка сообщений
Поток, вызывающий функцию sendMessageSendMessage, чтобы отправить сообщение другому потоку, не может продолжать выполняться до тех пор, пока не будет возвращена процедура окна, которая получает сообщение. Если получающий поток уступает управление во время обработки сообщения, поток отправки не может продолжать выполняться, так как ожидает, когда SendMessage вернется. Если поток-получатель привязан к той же очереди, что и отправитель, это может привести к взаимоблокировке приложения. (Обратите внимание, что хуки журнала присоединяют потоки к одной и той же очереди.)
Обратите внимание, что принимающему потоку не нужно явно передавать управление; вызов любой из следующих функций может привести к неявной передаче управления.
- Диалоговое окно
- DialogBoxIndirect
- DialogBoxIndirectParam
- DialogBoxParam
- GetMessage
- MessageBox
- PeekMessage
- ОтправитьСообщение
Чтобы избежать потенциальных взаимоблокировок в приложении, рекомендуется использовать функции SendNotifyMessage или SendMessageTimeout. В противном случае процедура окна может определить, было ли сообщение, которое она получила, отправлено другим потоком, вызвав функцию InSendMessage или InSendMessageEx. Перед вызовом любой из функций в предыдущем списке при обработке сообщения процедура окна должна сначала вызвать InSendMessage или InSendMessageEx. Если эта функция возвращает TRUE, процедура окна должна вызвать функцию ReplyMessage перед любой функцией, которая заставляет поток уступить управление.
Трансляция сообщений
Каждое сообщение состоит из идентификатора сообщения и двух параметров, wParam и lParam. Идентификатор сообщения — это уникальное значение, указывающее назначение сообщения. Параметры предоставляют дополнительные сведения, относящиеся к сообщению, но параметр wParam обычно является значением типа, предоставляющим дополнительные сведения о сообщении.
Широковещательная трансляция — это просто отправка сообщения нескольким получателям в системе. Чтобы транслировать сообщение из приложения, используйте функцию BroadcastSystemMessage, указав получателей сообщения. Вместо указания отдельных получателей необходимо указать один или несколько типов получателей. Эти типы являются приложениями, устанавливаемыми драйверами, сетевыми драйверами и драйверами устройств на уровне системы. Система отправляет широковещательные сообщения всем участникам каждого указанного типа.
Система обычно передает сообщения в ответ на изменения, происходящие в драйверах устройств на уровне системы или связанных компонентах. Драйвер или связанный компонент передает сообщение приложениям и другим компонентам, чтобы уведомить их об изменении. Например, компонент, ответственный за диски, передает сообщение, когда драйвер устройства для диска floppy обнаруживает изменение носителя, например, когда пользователь вставляет диск на диск.
Система передает сообщения получателям в этом порядке: драйверы устройств на уровне системы, сетевые драйверы, устанавливаемые драйверы и приложения. Это означает, что драйверы устройств на уровне системы, если они выбраны в качестве получателей, всегда получают первую возможность ответить на сообщение. В пределах заданного типа получателя ни один драйвер не гарантирует получение данного сообщения раньше других драйверов. Это означает, что сообщение, предназначенное для конкретного драйвера, должно иметь глобально уникальный идентификатор, чтобы ни один другой драйвер не обрабатывал его непреднамеренно.
Вы также можете транслировать сообщения во все окна верхнего уровня, указав HWND_BROADCAST в SendMessage, SendMessageCallback, SendMessageTimeoutили Функции SendNotifyMessage.
Приложения получают сообщения через процедуру окна верхнего уровня. Сообщения не отправляются в дочерние окна. Службы могут получать сообщения через оконную процедуру или их собственные обработчики управления.
Заметка
Драйверы устройств на уровне системы используют связанную функцию уровня системы для трансляции системных сообщений.
Запрос сообщений
Вы можете создать собственные пользовательские сообщения и использовать их для координации действий между приложениями и другими компонентами в системе. Это особенно полезно, если вы создали собственные устанавливаемые драйверы или драйверы устройств на уровне системы. Пользовательские сообщения могут переносить сведения в драйвер и приложения, использующие драйвер.
Чтобы опрашивать получателей разрешения на выполнение данного действия, используйте сообщение запроса. Вы можете создавать собственные сообщения запроса, задав значение BSF_QUERY в параметре dwFlags при вызове BroadcastSystemMessage. Каждый получатель сообщения запроса должен вернуть TRUE, чтобы функция отправила сообщение следующему получателю. Если любой получатель возвращает BROADCAST_QUERY_DENY, трансляция завершается немедленно, а функция возвращает ноль.