Чтобы ответить на ваш вопрос узко, каждое сообщение в очереди хранит, как минимум,
- дескриптор окна, на которое направлено сообщение,
- код сообщения, wParamи lParam, как вы уже правильно заметили,
- время публикации сообщения, которое вы извлекаете с помощью
GetMessageTime()
, - для сообщений интерфейса пользователя, положение курсора, когда сообщение было отправлено (см.
GetMessagePos()
).
Обратите внимание, что не все сообщения фактически сохраняются в очереди.Сообщения, которые отправляются с SendMessage()
в окно из потока, которому принадлежит окно, никогда не сохраняются;вместо этого функция сообщения окна получателя вызывается напрямую.Сообщения, отправленные из других потоков, сохраняются до их обработки, и поток-отправитель блокируется до тех пор, пока на сообщение не будет получен ответ, либо путем выхода из оконной функции, либо явным образом с вызовом ReplyMessage()
.Функция API InSendMessage()
помогает выяснить, обрабатывает ли функция Windows сообщение, отправленное из другого потока.
Сообщения, которые вы или системная публикация, сохраняются в очереди, за некоторыми исключениями.
Сообщения WM_TIMER фактически никогда не сохраняются сохраняются ;вместо этого GetMessage()
создает сообщение таймера, если в очереди нет других сообщений и таймер созрел.Это означает, что, во-первых, сообщения таймера имеют самый низкий приоритет удаления из очереди, и, во-вторых, что несколько сообщений из таймера с коротким периодом никогда не будут переполнены очередью, даже если GetMessage()
некоторое время не вызывается.В результате для данного таймера отправляется одиночное сообщение WM_TIMER, даже если таймер сработал несколько раз с момента обработки последнего сообщения WM_TIMER от этого таймера.
Аналогично, WM_QUIT также не сохраняется, а только помечается.GetMessage()
делает вид, что получил WM_QUIT после того, как очередь исчерпана, и это последнее полученное сообщение.
Другой пример - сообщение WM_PAINT (подсказка @ cody-серый за напоминание об этом).Это сообщение также имитируется, когда любая часть окна помечается как «грязная» и требует перекраски.Это также сообщение с низким приоритетом, созданное таким образом, что несколько недействительных областей в окне перекрашиваются одновременно, когда очередь становится пустой, чтобы уменьшить отзывчивость GUI и уменьшить мерцание.Вы можете принудительно перекрасить, позвонив по номеру UpdateWindow()
.Эта функция действует как SendMessage()
, в том смысле, что она не возвращается, пока открытая часть окна не будет фактически перерисована.Эта функция не отправляет WM_PAINT окну, если недопустимая область этого окна пуста, в качестве очевидной оптимизации.
Возможно, существуют другие исключения ивнутренние оптимизации.
Сообщения, отправленные с PostMessage()
, попадают в очередь потока, которому принадлежит окно, в которое отправляется сообщение.
В какой форме сообщения хранятся внутри, мыне знаю и нам пофиг.Windows API абстрагирует это полностью.Структура MSG заполняется в памяти, которую вы передаете GetMessage()
или PeekMessage()
.Вам не нужно знать или беспокоиться о деталях внутренней реализации помимо тех, которые описаны в руководствах по Windows SDK.
¹ Я не знаю, как именно WM_PAINT и WM_TIMER имеют приоритет относительно друг друга.Я предполагаю, что WM_PAINT имеет более низкий приоритет, но я могу ошибаться.