Студопедия

КАТЕГОРИИ:

АстрономияБиологияГеографияДругие языкиДругоеИнформатикаИсторияКультураЛитератураЛогикаМатематикаМедицинаМеханикаОбразованиеОхрана трудаПедагогикаПолитикаПравоПсихологияРиторикаСоциологияСпортСтроительствоТехнологияФизикаФилософияФинансыХимияЧерчениеЭкологияЭкономикаЭлектроника


Структура очереди сообщений




Теперь рассмотрим, откуда и какими путями сообщения попадают в функцию GetMessage. Обычное представление «сообщения выбираются из очереди» является большим упрощением ситуации. На самом деле, эта очередь устроена достаточно сложно.

Имеется два принципиально разных способа посылки сообщений: синхронный (send) и асинхронный (post). Посылая сообщение синхронно, отправитель дожидается окончания его обработки, прежде чем продолжить работу. Асинхронная посылка напоминает опускание письма в почтовый ящик: опустил и забыл. Система синхронным способом посылает окну сообщения о создании, изменении состояния и закрытии (например, WM_CREATE, WM_ACTIVATE, WM_SETFOCUS, WM_SETCURSOR, WM_DESTROY), а также многие другие сообщения. К асинхронным сообщениям относятся сообщения от клавиатуры и мыши, с некоторой оговоркой к ним можно отнести также WM_PAINT и WM_TIMER. Программа пользователя может посылать любые сообщения синхронным или асинхронным способом, как сочтет нужным разработчик. Выбор способа посылки зависит от того, насколько важно для программы-отправителя прежде, чем она продолжит работу, убедиться, что посланное сообщение получено и обработано адресатом.

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

· если отправитель сообщения и принимающее окно принадлежат разным процессам, то вызов оконной функции как подпрограммы просто невозможен, ибо процессы «не видят» друг друга, работая в разных виртуальных пространствах памяти;

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

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

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

Если отсутствуют сообщения в этой очереди, то черед доходит до аппаратных сообщений от клавиатуры и от мыши.

Общая схема аппаратного ввода показана на рисунке 2. Когда пользователь нажимает кнопку на клавиатуре или мыши, драйвер соответствующего устройства добавляет соответствующее событие в очередь аппаратного ввода (SHIQ). При появлении события в SHIQ пробуждается нить необработанного ввода (так называемая системная нить RIT), которая обычно бездействует. Эта нить преобразует событие в соответствующие сообщение (WM_KEY*, WM_xBUTTON или WM_MOUSEMOVE) и ставит последнее в соответствующую виртуальную очередь ввода (VIQ) нити, владеющей окном. Далее RIT возвращается в начало цикла и ждет появления следующего события в SHIQ.

 

Рис. 2. Модель аппаратного ввода

 

В случае сообщениий от мыши нить RIT направляет их в ту нить, которая владеет окном, на котором находился курсор в момент генерации сообщения. Исключение составляет случай, когда одно из окон с помощью функции SetCapture «захватило» мышь, т.е. хочет получать от нее сообщения со всего экрана. В современных версиях Windows захват в пределах всего экрана может действовать, только пока нажата какая-либо кнопка мыши. Это позволяет, например, пользователю «перетаскивать» объекты из активного окна в любое другое окно. После отпускания кнопок захват продолжает действовать только в пределах окон данной нити, поскольку разные приложения не должны мешать друг другу.

Сообщения от клавиатуры ведут себя несколько по-иному. В каждый момент времени нить RIT работает только с одной нитью (foreground thread), которой и принадлежит то окно, где работает пользователь. Как только пользователь переключается с окна одного приложения на окно другого приложения и это окно становится активным, RIT также переподключается к нити, владеющей этим окном.

Отметим, что ввод поступает именно в виртуальную очередь ввода нити, которой может принадлежать несколько окон, и для того чтобы сообщение было «доставлено» функцией DispatchMessage именно нужному окну, RIT добавляет дополнительную информацию в параметры сообщения. Существуют также сообщения, которые не направляются окнам приложений (например, известные комбинации клавиш Alt+Tab, Alt+Esc, Ctrl+Esc, Ctrl+Alt+Del и др.). Они обрабатываются непосредственно самой RIT: при поступлении такой комбинации с клавиатуры, нить RIT сама активизирует необходимое окно и переподключает его нить к себе, делая его активным.

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

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


Поделиться:

Дата добавления: 2015-09-15; просмотров: 64; Мы поможем в написании вашей работы!; Нарушение авторских прав





lektsii.com - Лекции.Ком - 2014-2024 год. (0.006 сек.) Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав
Главная страница Случайная страница Контакты