49086 (Сообщения и их обработка)

2016-07-30СтудИзба

Описание файла

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

Онлайн просмотр документа "49086"

Текст из документа "49086"

Сообщения и их обработка



Посылка сообщений



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

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

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

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

А во–вторых, накопление событий в очереди приложения помогает уменьшить количество переключений между приложениями, так как Windows обычно дает приложению полностью обработать события из его очереди и лишь после этого переключается на другие приложения. Кроме того, некоторые события могут группироваться в одно во время нахождения в очереди.



Рисунок 1 Маршрутизация сообщений в Windows 3.x



Извлечение сообщений из очереди приложения и направление их соответствующим окнам осуществляет функция WinMain. Этот процесс выполняется в несколько приемов:

сообщение выбирается из очереди с помощью функции GetMessage или PeekMessage

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

И только после этого оно направляется окну с помощью функции DispatchMessage (это называется диспетчеризацией)

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

MSG msg;

while (GetMessage(&msg, NULL, NULL, NULL)) {

TranslateMessage(&msg);

DispatchMessage(&msg);}

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

BOOL GetMessage(lpMsg, hWnd, uMsgFilterMin, uMsgFilterMax);

lpMsg указывает на структуру MSG, в которую будет записано полученное сообщение. Если очередь сообщений пуста, то GetMessage передает управление оболочке, так что та может начать обработку сообщений другого приложения.

Какие же данные передаются сообщением?

typedef struct tagMSG {

HWND hwnd; // хендл окна-получателя

UINT message; // номер сообщения WM_...

WPARAM wParam; // параметр сообщения

LPARAM lParam; // параметр сообщения

DWORD time; // время поступления сообщения

POINT pt; // координаты сообщения (для сообщений мыши)

} MSG;

Поле message структуры MSG задает номер сообщения, посланного системой. Интерпретация параметров сообщения wParam и lParam зависит от самого сообщения. Для этого надо смотреть описание конкретного сообщения и обрабатывать параметры соответствующим образом. Так как в системе определено огромное количество разных сообщений, то для простоты использования применяются символические имена сообщений, задаваемыми с помощью #define в заголовочном файле. В качестве примера можно привести сообщения WM_CREATE, WM_PAINT, WM_QUIT.

hWnd указывает хендл окна, сообщения для которого будут выбираться из очереди. Если hWnd равен NULL, то будут выбираться сообщения для всех окон данного приложения, а если hWnd указывает реальное окно, то из очереди будут выбираться все сообщения, направленные этому окну или его потомкам (дочерним или используемым окнами, или их потомкам, в том числе отдаленным).

uMsgFilterMin и uMsgFilterMax обычно установлены в NULL. Вообще они задают фильтр для сообщений. GetMessage выбирает из очереди сообщения, номера (имена) которых лежат в интервале от uMsgFilterMin до uMsgFilterMax. Нулевые значения исключают фильтрацию.

Функция GetMessage возвращает во всех случаях, кроме одного, ненулевое значение, указывающее, что цикл надо продолжать. Только в одном случае эта функция возвратит 0 — если она извлечет из очереди сообщение WM_QUIT. Это сообщение посылается только при окончании работы приложения.

После завершения цикла надо сделать совсем немногое — освободить память от тех объектов, которые создавались во время работы приложения (если они еще существуют). Некоторые объекты, которые уничтожаются автоматически, можно не освобождать — это сделает Windows. Таков, например, зарегистрированный нами класс окон.

И остается еще одно дело: так как WinMain возвращает результат, то мы должны вернуть какое–либо значение. В Windows принято, что возвращаемое значение является параметром wParam сообщения WM_QUIT, завершившего цикл обработки сообщений. Таким образом мы пишем:

return msg.wParam;



Посылка и передача сообщений



Ранее, в разделе “Ошибка! Источник ссылки не найден.”, мы рассматривали метод передачи сообщений, называемый посылкой сообщений (post message), и их обработки — извлечения из очереди в цикле обработки сообщений, трансляции и последующей передачи оконной процедуре. Источниками таких сообщений могут быть как компоненты системы, например, клавиатурный драйвер, так и само приложение. Для посылки сообщения в API предусмотрена функция

BOOL PostMessage(hWnd, uMsg, wParam, lParam);

Эта функция ставит сообщение в очередь. Возвращаемое значение TRUE указывает, что сообщение поставлено в очередь, FALSE — возникла ошибка (например, ошибочно указанный адресат или очередь сообщений переполнилась). Позже сообщение будет извлечено из очереди вызовом функции GetMessage или PeekMessage в цикле обработки сообщений.

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

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

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

LONG SendMessage(hWnd, uMsg, wParam, lParam);

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

Многие функции API используют SendMessage для передачи сообщений окну. Например, функция CreateWindow, создающая окно, в процессе создания передает ему сообщение WM_CREATE (и не только одно это сообщение), а результат, возвращенный обработчиком сообщения, используется функцией CreateWindow для продолжения создания окна.

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

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

Иногда сообщения передаются не какому–либо конкретному окну и не какому–либо приложению (потоку), а всем приложениям, запущенным в системе. Для этого используются широковещательные сообщения (broadcast message), которые передаются всем главным окнам всех приложений. Для передачи такого сообщения необходимо указать в качестве хендла окна–получателя специальный символ HWND_BROADCAST (равный -1), например:

SendMessage(HWND_BROADCAST, WM_DDE_INITIATE, (WPARAM)hwndDDEClient, 0L);

В этом случае сообщение WM_DDE_INITIATE будет передано главным окнам всех приложений, так что все работающие DDE–сервера смогут на него ответить.

Существенная особенность широковещательных сообщений — то, что они будут обрабатываться сразу большим количеством окон. То есть получить результат от обработчика этого сообщения обычным путем нельзя, так как остается неопределенность, результат какого обработчика возвращать. В частном случае (Win32 API) можно получить ответы от всех обработчиков с помощью функции SendMessageCallback. В общем случае при необходимости получения ответа от обработчика тот должен передать ответное сообщение (именно так сделано при установлении DDE–разговора).



Особенности посылки сообщений в Windows API



Помимо рассмотренных функций в Windows API существует еще две функции, посылающие сообщения. С одной из них — PostQuitMessage мы уже встречались в примере 1A. Эта функция посылает сообщение WM_QUIT, которое служит для завершения цикла обработки сообщений.

BOOL PostQuitMessage(wParam);

Сообщение WM_QUIT интересно еще и тем, что оно не посылается никакому окну — хендл окна–получателя равен NULL. В принципе у вас есть возможность самому посылать такие сообщения своему приложению, однако для этого обычная функция PostMessage не подходит. Вместо нее предусмотрена другая функция

BOOL PostAppMessage(hTask, uMsg, wParam, lParam);

Эта функция направляет сообщение приложению, указанному хендлом задачи hTask3. Для получения этого хендла можно воспользоваться функциями GetCurrentTask или GetWindowTask.

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

BOOL SetMessageQueue(cMaxMsg);

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



Особенности посылки и передачи сообщений в Win32 API



В Win32 в связи с появлением многопотоковых приложений изменился процесс маршрутизации сообщений в системе. Теперь очередь сообщений принадлежит не приложению (процессу), а потоку, создавшему ее. Поток, не использующий очередей и, соответственно, не имеющий цикла обработки сообщений, называется рабочим потоком (worker thread), а поток, работающий с окнами, создающий свою очередь и цикл обработки сообщений называется интерфейсным потоком (interface thread). В одном приложении Win32 может оказаться несколько рабочих потоков, несколько интерфейсных потоков и, соответственно, несколько очередей одновременно.

Еще одно отличие связано с тем, что размер очереди больше не фиксирован — при необходимости очередь динамически увеличивается. Благодаря этому функция SetMessageQueue больше не применяется.

Возможность применения нескольких интерфейсных потоков в одном процессе приводит дополнительно к отказу от функции PostAppMessage — так как остается неясно, какому потоку надо послать сообщение, и к добавлению функции:

Свежие статьи
Популярно сейчас
Зачем заказывать выполнение своего задания, если оно уже было выполнено много много раз? Его можно просто купить или даже скачать бесплатно на СтудИзбе. Найдите нужный учебный материал у нас!
Ответы на популярные вопросы
Да! Наши авторы собирают и выкладывают те работы, которые сдаются в Вашем учебном заведении ежегодно и уже проверены преподавателями.
Да! У нас любой человек может выложить любую учебную работу и зарабатывать на её продажах! Но каждый учебный материал публикуется только после тщательной проверки администрацией.
Вернём деньги! А если быть более точными, то автору даётся немного времени на исправление, а если не исправит или выйдет время, то вернём деньги в полном объёме!
Да! На равне с готовыми студенческими работами у нас продаются услуги. Цены на услуги видны сразу, то есть Вам нужно только указать параметры и сразу можно оплачивать.
Отзывы студентов
Ставлю 10/10
Все нравится, очень удобный сайт, помогает в учебе. Кроме этого, можно заработать самому, выставляя готовые учебные материалы на продажу здесь. Рейтинги и отзывы на преподавателей очень помогают сориентироваться в начале нового семестра. Спасибо за такую функцию. Ставлю максимальную оценку.
Лучшая платформа для успешной сдачи сессии
Познакомился со СтудИзбой благодаря своему другу, очень нравится интерфейс, количество доступных файлов, цена, в общем, все прекрасно. Даже сам продаю какие-то свои работы.
Студизба ван лав ❤
Очень офигенный сайт для студентов. Много полезных учебных материалов. Пользуюсь студизбой с октября 2021 года. Серьёзных нареканий нет. Хотелось бы, что бы ввели подписочную модель и сделали материалы дешевле 300 рублей в рамках подписки бесплатными.
Отличный сайт
Лично меня всё устраивает - и покупка, и продажа; и цены, и возможность предпросмотра куска файла, и обилие бесплатных файлов (в подборках по авторам, читай, ВУЗам и факультетам). Есть определённые баги, но всё решаемо, да и администраторы реагируют в течение суток.
Маленький отзыв о большом помощнике!
Студизба спасает в те моменты, когда сроки горят, а работ накопилось достаточно. Довольно удобный сайт с простой навигацией и огромным количеством материалов.
Студ. Изба как крупнейший сборник работ для студентов
Тут дофига бывает всего полезного. Печально, что бывают предметы по которым даже одного бесплатного решения нет, но это скорее вопрос к студентам. В остальном всё здорово.
Спасательный островок
Если уже не успеваешь разобраться или застрял на каком-то задание поможет тебе быстро и недорого решить твою проблему.
Всё и так отлично
Всё очень удобно. Особенно круто, что есть система бонусов и можно выводить остатки денег. Очень много качественных бесплатных файлов.
Отзыв о системе "Студизба"
Отличная платформа для распространения работ, востребованных студентами. Хорошо налаженная и качественная работа сайта, огромная база заданий и аудитория.
Отличный помощник
Отличный сайт с кучей полезных файлов, позволяющий найти много методичек / учебников / отзывов о вузах и преподователях.
Отлично помогает студентам в любой момент для решения трудных и незамедлительных задач
Хотелось бы больше конкретной информации о преподавателях. А так в принципе хороший сайт, всегда им пользуюсь и ни разу не было желания прекратить. Хороший сайт для помощи студентам, удобный и приятный интерфейс. Из недостатков можно выделить только отсутствия небольшого количества файлов.
Спасибо за шикарный сайт
Великолепный сайт на котором студент за не большие деньги может найти помощь с дз, проектами курсовыми, лабораторными, а также узнать отзывы на преподавателей и бесплатно скачать пособия.
Популярные преподаватели
Добавляйте материалы
и зарабатывайте!
Продажи идут автоматически
5167
Авторов
на СтудИзбе
437
Средний доход
с одного платного файла
Обучение Подробнее