Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
ОС лабы / ОС - Лабораторная работа 1.doc
Скачиваний:
63
Добавлен:
01.06.2015
Размер:
1.18 Mб
Скачать
      1. Асинхронная посылка сообщений

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

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

BOOL PostMessage( // Асинхронная посылка сообщения

// окну

HWND hWnd, // хэндл окна

UINT Msg, // тип сообщения

WPARAM wParam, // первый параметр сообщения

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

);

BOOL PostThreadMessage( // Асинхронная посылка

// сообщения для нити

DWORD idThread, // идентификатор нити

UINT Msg, // тип сообщения

WPARAM wParam, // первый параметр сообщения

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

);

Функция PostThreadMessageгенерирует сообщения с хэндлом окна-приемника, равнымNULL.

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

      1. Синхронная посылка сообщений

Синхронная посылка выполняется с помощью функции:

LRESULT SendMessage( // Синхронная посылка окну или нити

HWND hWnd, // хэндл окна-приемника

UINT Msg, // тип сообщения

WPARAM wParam, // первый параметр сообщения

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

);

Принципиальное отличие от асинхронной посылки заключается в том, что нить, пославшая сообщение, не возобновляет свою работу до тех пор, пока не будет получено подтверждение окончания обработки сообщения. Кроме того, при обработке некоторых типов сообщений программа может выдавать определенные данные в качестве ответа на сообщение. Для передачи ответа может использоваться либо результат, возвращаемый функцией SendMessage, либо содержимое области памяти, адресуемой одним из параметров сообщения. Выше отмечалось, например, что в ответ наWM_GETMINMAXINFOпрограмма может сообщить системе допустимые размеры окна, а результат обработкиWM_MOUSEACTIVATEопределяет, должна ли система активизировать окно. Разумеется, при асинхронной посылке отправитель не может получить достоверный ответ, поскольку не ждет окончания обработки.

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

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

  • выполнение вызванной оконной функции завершается;

  • оконная функция вызывает функцию ReplyMessage(означающую примерно следующее: «Пусть я еще не все сделала, но с оставшейся работой справлюсь сама, не стойте над душой»).

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

Что касается оконных функций, выполняющих обработку синхронных сообщений, следует отметить действующие ограничения на вызовы системных функций. Запрещено (по крайней мере, до вызова ReplyMessage) вызывать любые функции, которые могут вызвать переключение системы на выполнение другой нити. К таким функциям относятся, в частности,GetMessage,PeekMessage,WaitMessage,Yield,Sleep,SleepEx,WaitForSingleObject,WaitForMultipleObjects, а также функции, вызывающие запуск либо завершение процесса или нити.

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

Синхронная посылка сообщений имеет один принципиальный недостаток. Корректная работа приложения, посылающего сообщение, зависит от корректности поведения оконной функции окна-приемника. Если эта функция, например, зацикливается, не успев вызвать ReplyMessage, то нить, пославшая сообщение, блокируется навечно не по своей вине. Чтобы избежать такой ситуации,Windowsпредлагает на выбор три решения.

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

Функция SendMessageTimeoutаналогичнаSendMessage, однако ожидает ответа лишь в пределах указанного интервала времени.

Функция SendMessageCallbackзадает адрес функции, которая должна быть вызвана после окончания обработки посланного сообщения, при этом функция не ожидает немедленного ответа на сообщение.

    1. Программа Spy++

MicrosoftSpy++ – это программа, позволяющая получить в наглядном виде информацию о всех процессах в системе, нитях процессов (threads) и окнах, а также дающая возможность отслеживать поток сообщений.Spy++ входит в стандартную поставку пакетаMicrosoftVisualStudio.

Примерно такие же возможности, как Spy++, предоставляет программаWinSight32, поставляемая с продуктами фирмыBorland/Inprise. Имеются также бесплатные аналоги, например, программаWinspector. Любую из этих программ можно использовать для выполнения лабораторной работы, однако ниже будет описана работа только с программойSpy++ версии 8.00.

Интерфейс Spy++ достаточно прост и понятен. МенюSpyпозволяет открыть новое окно для просмотра потока сообщений (Log Messages), списка существующих окон (Windows), списка процессов (Processes) или нитей (Threads). В каждом окне можно выделить объект для дальнейшей работы. Можно также открыть несколько окон одного типа, например, для отслеживания сообщений, адресованных разным окнам.MенюWindowпозволяет переключаться между открытыми окнами.

Для выполнения данной работы наиболее ценной возможностью является просмотр (протоколирование) сообщений. Имеется несколько способов настройки просмотра на нужные сообщения. При выполнении команды Spy+Log Messagesоткрывается сначала диалогMessage Options, позволяющий указать, для каких окон следует отслеживать сообщения, какие именно сообщения и куда записывать протокол. На закладкеWindowsпользователь может выбрать конкретное окно на экране, оттащив на него значокFinder Tool. Разумеется, для этого окно должно быть видимо. Можно также добавить отображение сообщений для родительского окна, для дочерних окон, для всех окон той же нити или того же процесса либо для всех окон в системе. На закладкеMessagesвыбираются типы сообщений, которые нужно отслеживать. Можно включить или отключить целые группы сообщений (например, сообщения от клавиатуры или от командных кнопок) либо выбрать нужные сообщения из полного списка. На закладкеOutputпользователь может изменить формат и максимальное количество отображаемых сообщений.

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

Свойства выделенного объекта отображаются по команде View+Properties. Состав отображаемых свойств зависит от типа выбранного объекта.

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

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

Для окна отображается большое количество информации о его размерах, заголовке, стилях, классе, родительском окне, первом из дочерних окон, «братских» окнах, окне-владельце, а также о процессе и нити, которым принадлежит окно.

Свойства сообщения включают хэндл окна-приемника, уровень вложенности (т.е. окно верхнего уровня или дочернее), тип сообщения, способ посылки (SentилиPosted), а также значения параметров. Для большинства типов сообщений система пытается также расшифровать смысл параметровwParamиlParamв соответствии с описанными в документации поWindowsструктурами данных.

Для каждого отслеженного сообщения программа показывает его порядковый номер в протоколе, хэндл окна-получаателя, тип сообщения, способ посылки и, если тип сообщения известен программе, содержательный смысл параметров wParamиlParam. Для неизвестных программе сообщений (к которым относятся сообщения, определенные не в системеWindows, а в конкретной прикладной программе) указываются толькоwParamиlParam, без расшифровки. Способ посылки обозначается буквой:P– асинхронная посылка,S– синхронная посылка,R– ответ оконной функции на синхронную посылку. В ходе обработки одного синхронного сообщения могут посылаться и обрабатываться другие сообщения.

Меню Windowsпозволяет переключаться между ранее открытыми окнами. МенюTreeдает возможность изменять глубину вложения при отображении списков окон (показывать ли дочерние окна), процессов (показывать ли нити процесса) и нитей (показывать ли окна каждой нити).

Меню Messageактивно, только когда отображается поток сообщений. КомандаMessage+Logging Optionsдает возможность выбрать, для каких окон следует отслеживать сообщения, какие именно сообщения и куда записывать протокол. На закладкеWindowsпользователь может выбрать конкретное окно с помощьюFinder Tool. (Другой способ выбрать окно – выделить его в списке окон и выполнить команду контекстного менюMessages.) Можно также добавить отображение сообщений для родительского окна, для дочерних окон, для всех окон той же нити или того же процесса либо для всех окон в системе.

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

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

Команды Messages+Start LoggingиMessages+Stop Loggingвключают и выключают протоколирование сообщений. Чтобы сделать это поскорее (и тем самым сократить число ненужных сообщений), можно воспользоваться значком в панели инструментов или клавишейF8. КомандаMessages+Clearудаляет из окна все сообщения.

Для вывода копии протокола в файл можно использовать команду Messages+Save Log to File.

Команда контекстного меню Refreshобновляет содержимое текущего окна. Это может понадобиться, если состав отображаемых объектов изменился (например, были закрыты некоторые окна или открыты новые).