Главная | Обратная связь
МегаЛекции

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





 

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

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

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



Для посылки и передачи сообщений могут применяться следующие функции:

BOOL PostMessage( hWnd, wMsg, wPar, lPar );

Посылает указанное сообщение окну (через очередь сообщений).

LONG SendMessage( hWnd, wMsg, wPar, lPar );

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

BOOL PostAppMessage( hTask, wMsg, wPar, lPar );                     // Windows 3.x

BOOL PostAppMessage( dwProccessId, wMsg, wPar, lPar );         // Win32 API

BOOL PostThreadMessage( dwThreadId, wMsg, wPar, lPar ); // Win32 API

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

Хендл задачи hTask не является хендлом копии приложения. Вы можете использовать функцию GetCurrentTask для получения хендла задачи в среде Windows 3.x, а также функции GetCurrentThreadId и GetCurrentProcessId в Win32 API.

для получения этого хендла.

BOOL PostQuitMessage( wPar );

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

Типичные последовательности сообщений, получаемых окном.

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

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

Инициализация окна

 

Для создания окна используется функция CreateWindow(). Во время ее выполнения окно получает несколько сообщений:

WM_GETMINMAXINFO                 0  &MINMAXINFO

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

WM_NCCREATE 0                           &CREATESTRUCT

Создание внешней (non-client) области окна. Обработка, предусмотренная процедурой DefWindowProc() инициализирует необходимые структуры и, в частности, выделяет пространство для хранения заголовка окна. Никакого рисования не выполняется. Возвращаемый процедурой 0 указывает на возникшую ошибку и окно не создается; не 0 указывает на успешное создание внешней области.

WM_NCCALCSIZE flag &NCCALCSIZE_PARAMS

Определение размера внутренней (client) части окна; кроме этого определяется часть окна, которая может быть скопирована без изменений при перемещении окна или изменении его размеров.

WM_CREATE  0                           &CREATESTRUCT

Предусмотрено для выполнения Вами необходимых действий для создания внутренней (client) области окна. При этом Вы производите инициализацию связанных объектов, создание дочерних окон и пр. Как и WM_NCCREATE функция возвращает подтвержение о успешном выполнении нужных действий. Однако “успех” обозначается 0, а ошибка: -1 (!).

Активация приложения

 

Сейчас мы рассмотрим еще несколько последовательностей сообщений, получаемых главным окном приложения. Рассматривать мы их будем на примере создания и отображения главного окна приложения. Для начала мы выделим несколько сообщений в две обычных последовательности, которые можно назвать “активацией” и “деактивацией” приложения. Эти цепочки сообщений возникают при передаче активности (фокуса ввода) от одного приложения другому. За время работы одного приложения эти цепочки могут возникать многократно. Обычно сразу за созданием главного окна приложения следует активация этого приложения.

Активация приложения:

WM_ACTIVATEAPP                        TRUE   hTask

сообщение, информирующее об активации приложения. Если приложение имеет несколько окон “верхнего уровня” (т.е. окон стиля WS_OVERLAPPED или WS_POPUP), то все они получают эти сообщения. Младшее слово lParam содержит хендл той задачи, которая была активна до этого момента.

WM_NCACTIVATE                          TRUE   minimized & hWnd

активация (или деактивация, смотря по параметру wParam) внешней области окна. Обработка этого сообщения по умолчанию перерисовывает внешнюю область окна для выделения цветом активного/неактивного состояний. При этом активность или неактивность окна запоминается в структуре описания окна. Вы можете сами посылать WM_NCACTIVATE для изменения состояния окна. В документации параметр ‘lParam’ не описывается, однако он может быть не 0, и содержать такие же данные, как и в сообщении WM_ACTIVATE (см. ниже). Это сообщение может быть получено не только главным окном приложения, так как информирует об активации окна, а не приложения.

Если окно активируется, то возвращаемое значение может быть любым, а если деактивируется то значение 0 запрещает его дальнейшую деактивацию. Дочерние не MDI окна (стиль WS_CHILD) часто этого сообщения не получают.

WM_GETTEXT bufsize                  &buffer

при обработке этого сообщения указанный буфер заполняется названием активируемого окна. В данном случае это сообщение порождается при перерисовке внешней области окна - WM_GETTEXT “вложено” в обработку WM_NCACTIVATE. Если окно не имеет заголовка (caption bar), то это сообщение не посылается.

WM_ACTIVATE 1 или 2                minimized & hWnd

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

<получение фокуса ввода>

сообщения получения/потери фокуса ввода окном см. ниже.

В этой цепочке можно выделить две фазы:

1) активация приложения (если требуется)

2) активация окна, которая тоже выполняется в несколько фаз:

· активация внешней области

· активация внутренней области

Вся цепочка часто порождается функцией SetWindowPos(...); при этом такая цепочка входит в более сложную группу, начинающуюся с WM_WINDOWPOSCHAINGING и заканчивающуюся WM_WINDOWPOSCHANGED. При активации окна “щелчком мышкой” перед этой цепочкой проходит WM_MOUSEACTIVATE и пара сообщений WM_WINDOWPOSCHAINGING, WM_WINDOWPOSCHANGED. (См. ниже)

 

Деактивация приложения

 

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

WM_NCACTIVATE                          FALSE minimized & hWnd

деактивация начинается с сообщения о деактивации внешней области окна, о чем говорит параметр wParam == FALSE. Параметр lParam содержит в младшем слове хендл окна, становящегося активным, старшее указывает на состояние Вашего окна. (Более подробно - см. выше “активация приложения”)

WM_GETTEXT bufsize                  &buffer

Это сообщение порождается при перерисовке внешней области окна.

WM_ACTIVATE FALSE                 minimized & hWnd

затем деактивируется внутренняя область окна (wParam == FALSE). Параметр lParam содержит в младшем слове хендл окна, становящегося активным, старшее указывает на состояние Вашего окна.

WM_ACTIVATEAPP                        FALSE hTask

и в конце деактивируется все приложение. Параметр hTask указывает на приложение, которое становится активным.

<потеря фокуса ввода окном>

сообщения получения/потери фокуса ввода окном см. ниже.





Рекомендуемые страницы:

Воспользуйтесь поиском по сайту:
©2015- 2021 megalektsii.ru Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав.