Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
29
Добавлен:
02.05.2014
Размер:
384.51 Кб
Скачать

6.3.2. Обмен сообщениями

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

Архитектура объектно-ориентированных событийно управляемых приложений существенно отличается от традиционных "линейных" (ДОС) приложений.

Грубо архитектуру линейного приложения можно представить следующим образом:

Call Proc1;

Call Proc2;

Call ProcN;

Архитектуру объектно-ориентированного приложения можно представить следующим образом:

Это набор объектов – программных конструкций, отображающих объекты реального мира.

Объекты не могут существовать сами по себе. Им присуще стремление взаимодействовать друг с другом. Можно выделить два способа взаимодействия объектов:

  1. В методе одного объекта выполняется прямой вызов метода (который объявлен как доступный) другого объекта.

  2. Обмен сообщениями между объектами.

Прямой вызов

Взаимодействие объектов через сообщения

В сообщении указывается адрес получателя (другой объект) и данные. Некоторое средство, называемое Диспетчер, получает сообщения и перераспределяет их получателям.

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

Доступной архитектурой такого типа является архитектура Turbo Vision, реализованная в среде ДОС компанией Borland. Можно сказать, что это был предвестник объектно-ориентированного программирования в среде Windows. ДОС-приложение, написанное в среде Turbo Vision, почти ничем не отличается объектно-ориентированного Windows-приложения.

В Windows-среде функции диспетчера выполняет ядро ОС, а в качестве объектов выступают экземпляры оконных классов. Метод-обработчик сообщений называют оконной функцией.

ОС собирает информацию о всех событиях, происходящих в системе, и рассылает эту информацию оконным функциям, для которых информация предназначена.

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

Чтобы иметь возможность обмена сообщениями между объектами приложений, необходимо сообщение описать. Например:

UINT WM_SENDAPP;

Т.е. сообщение – это число целого типа.

Затем сообщение необходимо зарегистрировать в системе. Это делается функцией:

WM_SENDAPP = RegisterWindowMessage("SEND_APP");

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

В объявление класса, который должен обрабатывать сообщение, включается обработчик сообщения:

afx_msg LRESULT SendApp(WPARAM wParam,LPARAM lParam);

В реализации класса создается код обработчика:

LRESULT CName::SendApp(WPARAM wParam,LPARAM lParam) {

AfxMessageBox("Test message!");

if (wParam == ...) {

}

if (lParam == ...) {

}

return result;

}

Как осуществляется диспетчеризация (т.е. вызов нужного обработчика) сообщений? Надо реализовать оператор примерно следующего вида:

switch (msg) {

case WM_SENDAPP0 : SendApp0(wParam, lParam);

break;

case WM_SENDAPP1 : SendApp1(wParam, lParam);

break;

...

}

Если сообщений много, то оператор будет чрезвычайно громоздким. Поэтому создана другая технология, связывающая сообщение с обработчиком, называемая "message map". Идея состоит в том, что создается массив указателей на функции-обработчики, а индексами массива являются числовые значения сообщений.

На уровне приложения message map выглядит примерно следующим образом:

BEGIN_MESSAGE_MAP()

//{{AFX_MSG_MAP()

ON_WM_PAINT()

ON_REGISTERED_MESSAGE(WM_SENDAPP,SendApp)

//}}AFX_MSG_MAP

END_MESSAGE_MAP()

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

Другой тип сообщений, это сообщения, посылаемые объектам, минуя очередь. Этот вариант близок к варианту непосредственного вызова обработчика сообщения в объекте-получателе.

API Windows предлагает функции SendMessage() (синхронная) и PostMessage() (асинхронная) для обмена сообщениями между объектами.

Функция SendMessage() завершается, когда завершится выполнение обработчика сообщения в объекте-получателе и возвращает результат обработки, т.е. то значение, которое обработчик вернет оператором return.

Функция PostMessage() кладет сообщение в системную очередь и сразу же возвращает управление приложению. Тем самым исключаются задержки в выполнении приложения, но и отсутствует результат обработки сообщения.

Обе функции имеют одинаковый набор параметров:

BOOL PostMessage(

HWND hWnd, // получатель

UINT Msg, // сообщение

WPARAM wParam, // первый параметр

LPARAM lParam // второй параметр

);

Пример вызова функции:

if (!PostMessage(HWND_BROADCAST,WM_SENDAPP,1,1)) {

AfxMessageBox("Error");

}

6.3.3. Обмен данными через Clipboard

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

Традиционным способом использования Clipboard является обмен данными при участии пользователя.

Однако и другие, более развитые средства обмена данными, такие как DDE и OLE, используют концепции Clipboard в своей основе.

Важнейшей концепцией Clipboard является концепция формата данных.

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

Эта стандартизация позволила снять с пользователя проблемы преобразования данных при передаче их из одного приложения в другое, что и способствовало широкому распространению Clipboard. Среда сама берет на себя проблемы преобразования данных на основе ряда стандартных форматов.

Стандартизация форматов, однако, не ограничивает возможности их расширения.

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

RegisterClipboardFormat(строка с именем нового формата),

передав этой функции имя формата.

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

Стандартные форматы данных обозначаются константами, имеющими символические имена. Приведем в качестве примера пару таких форматов:

  1. cf_Text - ASCIIZ строка;

  2. cf_BitMap - один из форматов графического изображения.

Существует еще несколько (~25) стандартных форматов данных, поддерживаемых Clipboard.

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

Передача данных в Clipboard

Передача данных в Clipboard включает в себя ряд этапов.

  1. Подготовка данных для передачи в Clipboard;

  2. Открытие Clipboard;

  3. Очистка Clipboard;

  4. Посылка данных в Clipboard;

  5. Закрытие Clipboard.

Соседние файлы в папке Шпоры по СПО