Учебное пособие: Обмен данными в Windows
1) Вся работа с буфером обмена должна проводиться за время обработки одного сообщения. Во время работы с буфером Вы не должны вызывать никаких функций, которые могут передать управление другому приложению. То есть Вы не должны использовать функций типа: DialogBox, MessageBox, GetMessage, PeekMessage.
Данные должны размещаться только в перемещаемом блоке глобальной памяти.
Когда буфер обмена получает данные, он объявляет себя владельцем этих данных, так что приложение больше не должно использовать переданные данные. Более того, эти данные нельзя удалять при завершении работы Вашего приложения - когда будет надо, буфер обмена сам удалит их.
Когда Вы читаете данные из буфера обмена, то Вы получаете хендл блока данных. Так как эти данные закреплены за буфером, то Вы не должны с ними работать, Вам необходимо скопировать их к себе.
При обмене данными с буфером обмена нельзя передавать ему запертые блоки данных, равно как нельзя оставлять их запертыми после чтения.
2) Перед началом обмена данными с буфером обмена Вы должны его открыть. Делается это с помощью функции
BOOL OpenClipboard( hWnd );
если Вы положите какие-либо данные в буфер, то окно, указанное Вами, будет считаться владельцем всех данных буфера обмена.
3) Затем Вы можете осуществить необходимые операции обмена данными. Если Вы собираетесь положить данные в буфер обмена, то Вы должны предварительно удалить все уже находящиеся в нем данные:
BOOL EmptyClipboard( void );
и только затем положить нужные данные, воспользовавшись функцией:
HGLOBAL SetClipboardData( nFormat, hGlobal );
параметр nFormat задает имя формата данных, а hGlobal является хендлом глобального блока данных. Функция возвращает Вам новый хендл этого блока данных, с помощью которого Вы можете обращаться к этим данным до закрытия буфера обмена.
Вы можете положить в буфер обмена несколько блоков данных разного формата одновременно. Так как положенные в буфер данные сохраняются там либо до его очистки, либо до завершения работы Windows, то передавать большие блоки может быть слишком накладно.
Для этого случая в Windows предусмотрен механизм передачи данных с задержкой. Вызывая функцию SetClipboardData Вы указываете вместо хендла блока данных NULL. Это означает, что данные для буфер обмена у Вас есть, но передавать Вы их будете только по требованию. Для такой передачи Вам надо будет обрабатывать три сообщения:
WM_RENDERFORMAT nFormat 0L
сообщение требует данные для буфера обмена. При этом буфер уже открыт другим приложением, поэтому Вам открывать или закрывать его не надо. Вам надо просто вызвать функцию
SetClipboardData( nFormat, hGlobal );
передав ей хендл реального блока данных.
WM_RENDERALLFORMATS, 0, 0L
сообщение посылается Вашему окну когда оно уничтожается, а буфер обмена содержит задержанные данные Вашего окна. Вы должны обычным образом (то есть открыть–очистить–положить–закрыть) передать все данные в буфер обмена.
WM_DESTROYCLIPBOARD, 0, 0L
сообщение информирует Вас о том, что вызвана функция EmptyClipboard, когда буфер обмена содержит задержанные данные Вашего окна. Ваши данные больше не понадобятся, поэтому Вы можете освободить используемые структуры данных.
Если Вы собираетесь только читать данные из буфера обмена, то очищать его не надо, а получить данные нужного формата можно с помощью функции
HGLOBAL GetClipboardData( nFormat );
Функция возвращает хендл глобального блока памяти, который Вы должны скопировать к себе.
4) После завершения обмена с буфером обмена Вы должны закрыть его с помощью функции
BOOL CloseClipboard( void );
На этом заканчиваются операции обмена данными с буфером обмена.