SendMessageTimeout¶
SendMessageTimeout — это функция Windows API, предназначенная для отправки указанного сообщения в очередь сообщений одного или нескольких окон, с возможностью задания временного ограничения на выполнение операции. Относится к классу функций синхронного межпроцессного взаимодействия (IPC) и является расширенной версией функции SendMessage, добавляющей параметры тайм-аута и флагов поведения.
¶Функциональное назначение
SendMessageTimeout используется для отправки сообщения окну (или нескольким окнам) и ожидания его обработки в течение заданного времени. В отличие от SendMessage, которая блокирует вызывающий поток до завершения обработки сообщения получателем (что может привести к зависанию приложения, если окно-получатель не отвечает), SendMessageTimeout позволяет задать максимальное время ожидания. Если по истечении этого времени сообщение не было обработано, функция возвращает управление вызывающему потоку, предотвращая бесконечную блокировку.
¶Прототип и параметры
Функция объявлена в заголовочном файле winuser.h и экспортируется из библиотеки user32.dll. Прототип на языке C:
``c LRESULT SendMessageTimeout( HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, UINT fuFlags, UINT uTimeout, PDWORD lpdwResult ); ``
Параметры:
- hWnd — дескриптор окна-получателя. Если задан
HWND_BROADCAST(0xFFFF), сообщение отправляется всем окнам верхнего уровня в системе. - Msg — идентификатор сообщения (например,
WM_GETTEXT,WM_SETTEXT). - wParam, lParam — дополнительные параметры сообщения, зависят от типа сообщения.
- fuFlags — комбинация флагов, определяющих режим отправки:
SMTO_NORMAL(0x0000) — обычная отправка без специальных опций.SMTO_BLOCK(0x0001) — блокирует вызывающий поток до завершения обработки сообщения получателем (аналогично SendMessage, но с тайм-аутом).SMTO_ABORTIFHUNG(0x0002) — прерывает отправку, если окно-получатель находится в состоянии «зависания» (не отвечает на сообщения в течение определённого времени).SMTO_NOTIMEOUTIFNOTHUNG(0x0008) — игнорирует тайм-аут, если окно-получатель не зависло.- uTimeout — время ожидания в миллисекундах. Если значение равно нулю, функция немедленно возвращает управление.
- lpdwResult — указатель на переменную, в которую записывается результат обработки сообщения получателем. Может быть
NULL, если результат не требуется.
Возвращаемое значение:
- В случае успеха возвращает ненулевое значение (истина), а результат обработки сообщения помещается в
*lpdwResult. - В случае ошибки (например, тайм-аут, окно не найдено) возвращает 0 (ложь). Для получения расширенной информации об ошибке следует вызвать
GetLastError.
¶Поведение и особенности
¶Отправка одному окну
При указании конкретного дескриптора окна функция отправляет сообщение в очередь сообщений этого окна и ожидает его обработки. Если окно не отвечает в течение uTimeout миллисекунд, функция возвращает 0. Если окно обрабатывает сообщение до истечения тайм-аута, возвращается результат обработки.
¶Широковещательная отправка (HWND_BROADCAST)
При использовании HWND_BROADCAST сообщение отправляется всем окнам верхнего уровня (top-level windows) в системе. Функция ожидает завершения обработки каждым окном, но не более uTimeout миллисекунд на каждое окно. Общее время ожидания может значительно превышать uTimeout, если в системе много окон. Флаг SMTO_ABORTIFHUNG позволяет пропускать зависшие окна, ускоряя операцию.
¶Взаимодействие с потоками
SendMessageTimeout может использоваться для межпотокового общения в пределах одного процесса, если окна принадлежат разным потокам. Однако для общения между потоками одного процесса чаще применяются другие механизмы (например, PostMessage или пользовательские сообщения).
¶Ограничения и безопасность
- Функция не может отправлять сообщения окнам, принадлежащим процессам с более высоким уровнем целостности (UIPI — User Interface Privilege Isolation) в Windows Vista и новее. В таких случаях возвращается ошибка.
- Широковещательная отправка может быть заблокирована системой для некоторых сообщений (например,
WM_SETTEXT), чтобы предотвратить злонамеренное вмешательство в работу других приложений. - При использовании
SMTO_BLOCKвызывающий поток блокируется, что может привести к взаимоблокировке (deadlock), если два потока одновременно отправляют друг другу сообщения с ожиданием.
¶Пример использования
Следующий код на C++ демонстрирует отправку сообщения WM_GETTEXT для получения текста заголовка окна:
```cpp
¶include <windows.h>
¶include <iostream>
int main() { HWND hWnd = FindWindow(NULL, L"Блокнот"); // дескриптор окна "Блокнот" if (!hWnd) { std::cerr << "Окно не найдено" << std::endl; return 1; }
wchar_t buffer[256]; DWORD result; LRESULT ret = SendMessageTimeout( hWnd, WM_GETTEXT, sizeof(buffer) / sizeof(wchar_t), (LPARAM)buffer, SMTO_ABORTIFHUNG | SMTO_NORMAL, 5000, // тайм-аут 5 секунд &result );
if (ret) { std::wcout << L"Текст заголовка: " << buffer << std::endl; } else { std::cerr << "Ошибка отправки сообщения (код: " << GetLastError() << ")" << std::endl; }
return 0; } ```
¶Сравнение с другими функциями
| Функция | Блокировка | Тайм-аут | Широковещание | Результат обработки |
|---|---|---|---|---|
| SendMessage | Да | Нет | Да (HWND_BROADCAST) | Да |
| PostMessage | Нет | Нет | Да (HWND_BROADCAST) | Нет |
| SendMessageTimeout | Да (с тайм-аутом) | Да | Да | Да |
| SendNotifyMessage | Нет | Нет | Нет | Нет |
¶История и версии
Функция появилась в Windows 95 и Windows NT 4.0. В последующих версиях Windows её поведение было уточнено, в частности, добавлены флаги SMTO_NOTIMEOUTIFNOTHUNG (Windows 2000) и улучшена обработка широковещательных сообщений. В Windows Vista и новее функция учитывает UIPI, что может влиять на возможность отправки сообщений окнам с более высоким уровнем целостности.
¶Применение
SendMessageTimeout используется в ситуациях, когда необходимо отправить сообщение окну, но нежелательно бесконечно ждать его обработки. Типичные сценарии:
- Управление внешними окнами (например, закрытие, перемещение, изменение размера) с защитой от зависания.
- Получение данных от окон других приложений (например, текста из полей ввода) с контролем времени ожидания.
- Реализация тайм-аутов в пользовательских интерфейсах, где требуется синхронное взаимодействие с окнами, но без риска блокировки основного потока.
¶Критика и альтернативы
Основной недостаток SendMessageTimeout — потенциальная блокировка вызывающего потока, особенно при широковещательной отправке, когда функция ожидает ответа от каждого окна. В современных приложениях для межпроцессного взаимодействия часто предпочитают асинхронные механизмы (например, именованные каналы, сокеты, COM-интерфейсы), которые не блокируют поток и позволяют более гибко управлять временем ожидания. Для простого уведомления окон без ожидания ответа используется PostMessage.
¶Источники
- Microsoft Docs. "SendMessageTimeout function (winuser.h)".
- Рихтер Дж. "Windows via C/C++". 5-е издание, глава 10 "Механизмы синхронизации".
- Петцольд Ч. "Программирование для Windows 95". Глава 6 "Сообщения и обработка сообщений".
- MSDN Library. "User Interface Privilege Isolation (UIPI)".
- MSDN Magazine. "Windows API: SendMessage, PostMessage, and Related Functions".
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →


