Сведения о сообщениях и очередях сообщений

В отличие от приложений на основе MS-DOS, приложения на основе Windows управляются событиями. Они не выполняют явные вызовы функций (например, вызовы библиотеки времени выполнения C) для получения входных данных. Вместо этого они ожидают передачи системе входных данных.

Система передает все входные данные для приложения в различные окна в приложении. Каждое окно имеет функцию, называемую процедурой окна, которая вызывается системой всякий раз, когда она имеет входные данные для окна. Процедура окна обрабатывает входные данные и возвращает элемент управления в систему. Дополнительные сведения о процедурах окон см. в разделе "Процедуры окна".

Если окно верхнего уровня перестает отвечать на сообщения в течение более чем нескольких секунд, система считает, что окно не отвечает. В этом случае система скрывает окно и заменяет его фантомным окном с одинаковым порядком Z, расположением, размером и визуальными атрибутами. Это позволяет пользователю перемещать его, изменять его размер или даже закрывать приложение. Однако это единственные доступные действия, так как приложение фактически не отвечает. В режиме отладчика система не создает окно призрака.

В этом разделе рассматриваются следующие разделы:

сообщения Windows

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

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

Идентификатор сообщения — это именованной константой, определяющей назначение сообщения. Когда процедура окна получает сообщение, он использует идентификатор сообщения для определения способа обработки сообщения. Например, идентификатор сообщения WM_PAINT сообщает процедуре окна, что клиентская область окна изменилась и должна быть переопределена.

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

Типы сообщений

В этом разделе описываются два типа сообщений:

сообщения System-Defined

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

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

Символьные константы указывают категорию, к которой относятся системные сообщения. Префикс константы определяет тип окна, который может интерпретировать и обрабатывать сообщение. Ниже приведены префиксы и связанные с ними категории сообщений.

Prefix Категория сообщений Документация
ABM и ABN Панель инструментов рабочего стола приложения Сообщения и уведомления оболочки
ACM и ACN Элемент управления "Анимация" Уведомления об элементах управленияанимацией и анимации
BCM, BCN, BM и BN Button - элемент управления Уведомления об элементах управления "Кнопка" и "Управление кнопками"
CB и CBN ComboBox - элемент управления Сообщения элементов управления ComboBox и уведомления элементов управления ComboBox
CBEM и CBEN Элемент управления ComboBoxEx Сообщения ComboBoxEx и уведомления ComboBoxEx
СКК Общий элемент управления Управление сообщениями
CDM Общее диалоговое окно Распространенные сообщения диалогового окна
DFM Контекстное меню по умолчанию Сообщения и уведомления оболочки
DL Перетащите поле со списком Перетаскивание уведомлений по списку
DM Элемент управления кнопкой нажатия по умолчанию Сообщения диалогового окна
DTM и DTN Элемент управления "Выбор даты и времени" Сообщения средства выбора даты и времени и уведомления средства выбора даты и времени
EM и EN Элемент управления "Поле ввода" Изменение сообщений элементов управления, изменение уведомлений элемента управления, форматированные сообщения редактирования и уведомления с расширенными возможностями редактирования
HDM и HDN Элемент управления "Заголовок" Сообщения элементов управления заголовком и уведомления элемента управления заголовками
HKM Элемент управления "Горячий ключ" Сообщения о горячем элементе управления ключами
IPM и IPN контроль IP-адресов Уведомления об IP-адресах и IP-адресах
LB и LBN Элемент управления "Список" Сообщения списка и уведомления о списке
LM Элемент управления SysLink Сообщения элемента управления SysLink
LVM и LVN Элемент управления представлением списка Уведомления представления списка и представления списка
MCM и MCN Элемент управления "Календарь месяца" Сообщения календаря месяца и уведомления календаря месяца
Управление на основе политик (PBM) Индикатор выполнения Сообщения индикатора выполнения
PGM и PGN Элемент управления Pager Сообщения элемента управления Pager и уведомления элемента управления Pager
PSM и PSN Страница свойств. Сообщения иуведомления листа свойств
RB и RBN Элемент управления "Перебар" Панели управления сообщениями и уведомлениями элемента управления "Перебара"
SB и SBN Окно строки состояния Сообщения строки состояния и уведомления строки состояния
SBM Элемент управления "Полоса прокрутки" Сообщения полосы прокрутки
SMC Меню оболочки Сообщения и уведомления оболочки
STM и STN Статический элемент управления Сообщения статического элемента управления и уведомления о статических элементах управления
ТБ и TBN Панель инструментов Уведомления об элементах управления панели инструментов и панели инструментов
TBM и TRBN Элемент управления Trackbar Сообщения элементов управления Trackbar и уведомления элемента управления Trackbar
TCM и TCN Элемент управления табуляции Сообщения элементов управления вкладками и уведомления элемента управления tab
TDM и TDN Диалоговое окно задачи Сообщения диалогового окна задач и уведомления о диалоговых окнах задач
TTM и TTN Элемент управления подсказкой Уведомления элементов управления подсказками и всплывающих подсказок
TVM и TVN Элемент управления "Представление дерева" Сообщения в виде дерева и уведомления в виде дерева
UDM и UDN Элемент управления "Вверх вниз" Сообщения вверх иуведомления вверх вниз
WM Общее
Сообщения буфера обмена
Уведомления буфера обмена
Распространенные уведомления в диалоговом окне
Уведомления курсоров
Сообщение копирования данных
Сообщения диспетчера окон рабочего стола
сообщения Управление устройствами
Уведомления в диалоговом окне
Сообщения Exchange динамических данных
Уведомления Exchange динамических данных
Уведомления об перехватчике
Сообщения акселератора клавиатуры
Уведомления акселератора клавиатуры
Ввод с клавиатуры сообщений
Уведомления ввода с клавиатуры
Уведомления меню
Уведомления ввода мыши
Несколько сообщений интерфейса документа
Необработанные входные уведомления
Уведомления полосы прокрутки
Уведомления таймера
Сообщения окна
Уведомления о окне

Общие сообщения о окне охватывают широкий спектр сведений и запросов, включая сообщения для ввода мыши и клавиатуры, ввода меню и диалогового окна, создания окна и управления и динамического Exchange (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. Большинство других сообщений, отправляемых непосредственно в процедуру окна, называются неqueued.

Сообщения в очереди

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

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

Когда пользователь перемещает мышь, нажимает кнопки мыши или вводит их на клавиатуре, драйвер устройства для мыши или клавиатуры преобразует входные данные в сообщения и помещает их в очередь системных сообщений. Система удаляет сообщения по одному из системной очереди сообщений, проверяет их, чтобы определить целевое окно, а затем отправляет их в очередь сообщений потока, создавшего целевое окно. Очередь сообщений потока получает все сообщения мыши и клавиатуры для окон, созданных потоком. Поток удаляет сообщения из очереди и направляет систему на отправку их в соответствующую процедуру окна для обработки.

За исключением сообщения 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 для перемещения окна.

Некоторые функции, которые отправляют неqueued сообщения: BroadcastSystemMessage, BroadcastSystemMessageEx, SendMessage, SendMessageTimeout и SendNotifyMessage.

Обработка сообщений

Приложение должно удалять и обрабатывать сообщения, опубликованные в очередях сообщений своих потоков. Однопоточное приложение обычно использует цикл сообщений в функции WinMain для удаления и отправки сообщений в соответствующие процедуры окна для обработки. Приложения с несколькими потоками могут включать цикл сообщений в каждый поток, который создает окно. В следующих разделах описывается, как работает цикл сообщений, и объясняется роль процедуры окна:

Loop сообщений

Простой цикл сообщений состоит из одного вызова функции для каждой из этих трех функций: 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 процедура окна может определить, обрабатывается ли сообщение, отправленное другим потоком. Эта возможность полезна, если обработка сообщений зависит от источника сообщения.

Взаимоблокировки сообщений

Поток, вызывающий функцию SendMessage для отправки сообщения другому потоку, не может продолжать выполняться до тех пор, пока не будет возвращена процедура окна, получающая сообщение. Если принимающий поток возвращает элемент управления во время обработки сообщения, отправляющий поток не может продолжить выполнение, так как он ожидает возврата SendMessage . Если принимающий поток подключен к той же очереди, что и отправитель, это может привести к взаимоблокировке приложения. (Обратите внимание, что обработчики журнала присоединяют потоки к одной очереди.)

Обратите внимание, что принимающему потоку не требуется явное управление получением; Вызов любой из следующих функций может привести к неявно получению элемента управления потоком.

Чтобы избежать потенциальных взаимоблокировок в приложении, рассмотрите возможность использования функций SendNotifyMessage или SendMessageTimeout . В противном случае процедура окна может определить, было ли полученное сообщение отправлено другим потоком, вызвав функцию InSendMessage или InSendMessageEx . Перед вызовом любой из функций в предыдущем списке во время обработки сообщения процедура окна должна сначала вызвать InSendMessage или InSendMessageEx. Если эта функция возвращает значение TRUE, процедура окна должна вызвать функцию ReplyMessage , прежде чем любая функция, которая приводит к получению элемента управления потоком.

Трансляция сообщений

Каждое сообщение состоит из идентификатора сообщения и двух параметров, wParam и lParam. Идентификатор сообщения — это уникальное значение, указывающее назначение сообщения. Параметры предоставляют дополнительные сведения, относящиеся к сообщению, но параметр wParam обычно является значением типа, предоставляющим дополнительные сведения о сообщении.

Широковещательная рассылка сообщений — это просто отправка сообщения нескольким получателям в системе. Чтобы транслировать сообщение из приложения, используйте функцию BroadcastSystemMessage , указав получателей сообщения. Вместо указания отдельных получателей необходимо указать один или несколько типов получателей. Эти типы являются приложениями, устанавливаемыми драйверами, сетевыми драйверами и драйверами устройств на уровне системы. Система отправляет широковещательные сообщения всем членам каждого указанного типа.

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

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

Вы также можете транслировать сообщения во все окна верхнего уровня, указав HWND_BROADCAST в функции SendMessage, SendMessageCallback, SendMessageTimeout или SendNotifyMessage.

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

Примечание

Драйверы устройств на уровне системы используют связанную функцию уровня системы для трансляции системных сообщений.

Запрос сообщений

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

Чтобы опрашивать получателей разрешения на выполнение заданного действия, используйте сообщение запроса. Вы можете создавать собственные сообщения запроса, задав значение BSF_QUERY в параметре dwFlags при вызове BroadcastSystemMessage. Каждый получатель сообщения запроса должен возвращать значение TRUE , чтобы функция отправляла сообщение следующему получателю. Если любой получатель возвращает BROADCAST_QUERY_DENY, трансляция завершается немедленно, а функция возвращает ноль.