Учебное пособие: Обмен данными в Windows
В какой-то степени это похоже на обработку прерываний DOS - система удерживает хендл только первого окна просмотра, тот - хендл следующего и так далее.
Когда Вы запускаете свою программу просмотра, она регистрируется в качестве программы просмотра буфера обмена с помощью функции
HWND SetClipboardViewer( hWnd );
при этом он становится на первое место в цепочке, а функция SetClipboardViewer возвращает хендл следующего за ним (или 0, если других программ (окон) просмотра нет). Этот хендл должен быть сохранен.
Далее, при обновлении данных в буфере обмена, Ваше окно получает сообщение WM_DRAWCLIPBOARD. Обычнаяобработкаэтогосообщения:
case WM_DRAWCLIPBOARD: if ( hWndNextViewer ) PostMessage( hWndNextViewer, wMsg, wParam, lParam ); InvalidateRect( hWnd, NULL, TRUE ); return 0;
В результате обработки этого сообщения окно программы просмотра перерисовывается, и такое же сообщение получает другая программа.
Во время нормальной работы какая-либо из программ просмотра заканчивает функционирование прежде остальных. При этом цепочка программ просмотра изменяется. Для того, чтобы корректно изменить цепочку, применяется функция
BOOL ChangeClipboardChain( hWndViewer, hWndNextViewer );
Что значит: вместо окна hWndViewer будет использоваться окно hWndNextViewer. Эта функция обычно вызывается при обработке сообщения WM_DESTROY. В результате выполнения этой функции первая программа просмотра в цепочке получит сообщение (WM_CHANGECBCHAIN, hWndRemoved, hWndNext). Это сообщение обрабатывается так:
case WM_CHANGECBCHAIN: if ( wParam == hWndNextViewer ) { hWndNextViewer= LOWORD( lParam ); } else if ( hWndNextViewer ) { PostMessage( hWndNextViewer, wMsg, wParam, lParam ); } return 0;
В результате такой обработки, если наше окно стоит в цепочке до удаляемого, но не прямо перед ним, оно передаст сообщение дальше; если оно стоит прямо перед удаляемым, то оно исправит свой хендл следующего окна просмотра и не пустит сообщение дальше, так как цепочка уже исправлена.
Отображение данных программой просмотра происходит также, как и их обычное чтение (открыл–прочитал–закрыл).
Динамический обмен данными (DDE)
Пока что мы рассмотрели только один способ обмениваться данными между разными приложениями - буфер обмена. Однако этот способ не всегда эффективен. В большинстве случаев он ограничен применением в редакторах.
Однако необходимость обмена данными между разными приложениями реально существует, поэтому Windows содержит еще одно средство для такого обмена — DDE (Dynamic Data Exchange).
DDE основан на использовании сообщений для передачи данных между двумя приложениями. При этом одно из приложений (обычно содержащее данные) называется сервером (server), а другое (обычно требующее данных) – клиентом (client). В более общем виде: клиент выступает в роли активного приложения, требующего, что бы его запросы были обслужены сервером. Сам процесс обмена данными средствами DDE между клиентом и сервером называется DDE–разговором (DDE–conversation).
Обычно протокол обмена данными между клиентом и сервером выглядит примерно следующим образом:
· клиент передает всем доступным приложениям сообщение о том, что ему надо.
· если в системе находится подходящий сервер, он отвечает клиенту о возможности обслуживания.
· клиент посылает запрос(ы) серверу для выполнения требований.
· в некоторых случаях сервер может информировать клиента об изменении или наличии тех или иных данных. Для этого клиент должен подписаться (advise) на необходимые данные.
· обмен между клиентом и сервером может продолжаться до тех пор, пока один из них не потребует прекращения.
В процессе DDE–разговора происходит обмен сообщениями между двумя приложениями. Понятно, что адресатами таких сообщений являются не сами приложения, а их окна. В большинстве случаев для нормального ведения DDE–разговора создаются специальные скрытые (невидимые) окна, которые и осуществляют обмен сообщениями между собой. Конечно, в DDE могут участвовать окна одного приложения, не только разных, но надо учесть, что DDE для обмена данными в пределах одного приложения является неэффективным. Так как процессы подготовки и приема данных могут занимать значительное время, то требуется, чтобы для обмена сообщениями использовалась функция PostMessage, а не SendMessage (кроме установления DDE–разговора). Это, правда, создает дополнительную сложность — необходимость синхронизации действий разных окон между собой.
В Windows содержится все необходимое для организации DDE, причем в двух экземплярах. Помимо старого способа, существующего с первых версий Windows, в Windows версии 3.1 была добавлена специальная библиотека DDEML (DDE Management Library), являющаяся “надстройкой” над старым способом и предназначенная для формализации протоколов обмена. Существенная разница между этими способами связана с тем, что для организации DDE старым способом вы должны предусмотреть обработку специальных сообщений необходимыми Вам окнами, а библиотека DDEML сама создает необходимые скрытые окна и организует обмен сообщениями; при этом для взаимодействия с Вашим приложением DDEML будет вызывать специально разработанную Вами CALLBACK процедуру (не являющую оконной процедурой).
Считается, что при использовании DDEML несколько упрощается написание приложений, так как она берет на себя вопросы синхронизации обмена. Однако на практике не было замечено реального упрощения работы в связи с применением библиотеки. Более того, исходный текст может оказаться даже больше, чем при использовании старого метода.
Поэтому мы будем рассматривать только старый способ организации DDE. Предварительно мы введем несколько терминов, используемых в DDE. Когда клиент начинает DDE или требует данные, он посылает серверу спецификацию того, что он требует.
Эта спецификация состоит из 3 пунктов:
· имя приложения — application (в DDEML называется сервис (service)); так как в большинстве случаев в документации применяется термин service, то его мы и будем использовать дальше. Хотя, надо отметить, этот параметр обычно задает условное имя приложения–сервера.
· тему DDE–разговора — topic