Нестандартный формат данных
Для обмена данными между одновременно работающими копиями одного и того же приложения, а также для копирования фрагментов документа в рамках одной копии приложения не всегда удобно использовать стандартные форматы данных Clipboard. Дело в том, что внутренняя структура таких фрагментов может быть сложнее, чем обычный текст или битовое изображение.
Конечно, можно создать свой, нестандартный формат данных, пользуясь одним из стандартных форматов, например, текстовым CF_TEXT или каким либо еще, добавив к тексту или изображению дополнительные данные. Однако вставка пользователем фрагмента документа в таком "полустандартном" формате в произвольное приложение, не рассчитанное на этот формат, может привести к неожиданным результатам.
Поэтому лучшим решением будет создание собственного формата данных для записи в Clipboard.
Как создать свой формат данных для записи в Clipboard?
Для этого достаточно зарегистрировать формат данных при помощи функции RegisterClipboardFormat:
UINT WINAPI RegisterClipboardFormat(LPCSTR lpszFormatName);
В качестве параметра этой функции следует передать указатель на текстовую строку, закрытую двоичным нулем и содержащую имя регистрируемого вашим приложением нестандартного формата данных для Clipboard.
Функция возвращает нулевое значение при ошибке или идентификатор зарегистрированного формата данных, который можно использовать аналогично идентификаторам стандартных форматов в качестве параметра функции SetClipboardData.
Два различных приложения, две копии одного приложения могут зарегистрировать формат с одним и тем же именем, при этом функция RegisterClipboardFormat вернет один и тот же идентификатор формата. Поэтому два приложения всегда смогут "договориться", если они знают имя нестандартного формата данных.
При использовании нестандартного формата данных возникает проблема отображения этих данных приложениями, предназначенными для динамического просмотра содержимого Clipboard, а также проблема вставки нестандартных данных в приложения, не рассчитанные на этот формат данных.
Можно частично решить эту проблему, использовав так называемые форматы отображения (display formats) CF_DSPTEXT, CF_DSPBITMAP и CF_DSPMETAFILEPICT. Эти форматы предназначены для представления, соответственно, текстовых данных, битовых изображений и метафайлов. Обычные приложения не воспринимают форматы отображения, поэтому для них следует записать в Clipboard данные не только в форматах отображения, но и в стандартных форматах.
Форматы отображения не всегда позволяют точно изобразить данные, которые записаны в Clipboard в нестандартном формате. Например, текстовый процессор может записать в Clipboard текст и параметры его шрифтового оформления. Форматы CF_TEXT и CF_DSPTEXT не позволяют передать особенности шрифтового оформления, поэтому при просмотре содержимого Clipboard вы увидите "сырой" текст, набранный системным шрифтом.
Как же заставить приложение, предназначенное для просмотра Clipboard, максимально точно отобразить нестандартные данные, записанные приложением?
Для этого следует воспользоваться форматом данных CF_OWNERDISPLAY. Если ваше приложение при вызове функции SetClipboardData указывает этот формат данных, отображение в окне просмотра Clipboard будет выполнять то приложение, которое записало нестандартные данные.
Приложение, создавшее окно просмотра Clipboard, при отображении данных в формате CF_OWNERDISPLAY посылает владельцу Clipboard сообщения, связанные с отображением в окне просмотра.
Когда приложение-владелец Clipboard должен нарисовать нестандартные данные в окне просмотра, оно получает сообщение WM_PAINTCLIPBOARD. Отметим, что это сообщение посылает не Windows, а приложение, создавшее окно просмотра Clipboard (если оно рассчитано на отображение данных в формате CF_OWNERDISPLAY).
Параметр wParam сообщения WM_PAINTCLIPBOARD содержит идентификатор окна просмотра Clipboard, в котором нужно нарисовать данные.
Через параметр lParam передается идентификатор глобального блока памяти, содержащего структуру типа PAINTSTRUCT, определяющую внутреннюю область окна просмотра.
Перед использованием блок памяти следует зафиксировать функцией GlobalLock, а после использования - расфиксировать функцией GlobalUnlock.
Когда окно просмотра Clipboard изменяет свои размеры, владелец Clipboard, записавший туда данные в формате CF_OWNERDISPLAY, получит сообщение WM_SIZECLIPBOARD.
Параметр wParam сообщения WM_SIZECLIPBOARD содержит идентификатор окна просмотра Clipboard. Через параметр lParam передается идентификатор глобального блока памяти, содержащего структуру типа RECT, определяющую новые размеры внутренней области окна просмотра Clipboard.
Есть еще три сообщения, которые владелец Clipboard получает от окна просмотра Clipboard.
Сообщение WM_ACKCBFORMATNAME посылается окном просмотра, для того чтобы получить от владельца Clipboard имя нестандартного формата, использованное в процессе регистрации. Это имя будет отображено в списке доступных для отображения форматов данных.
Параметр lParam сообщения WM_ACKCBFORMATNAME содержит указатель на буфер, в который нужно скопировать текстовую строку имени нестандартного формата, закрытую двоичным нулем. Размер буфера задается параметром wParam.
Окно просмотра Clipboard может быть снабжено полосами просмотра. Поэтому владелец Clipboard может получить сообщения WM_HSCROLLCLIPBOARD и WM_VSCROLLCLIPBOARD. В процессе обработки сообщений владелец Clipboard может использовать функцию ScrollWindow для свертки окна просмотра.
Параметр wParam этих сообщений содержит идентификатор окна просмотра Clipboard. Через младшее слово параметра lParam передается код полосы просмотра (константы с префиксом имени SB, такие как SB_TOP, SB_BOTTOM, SB_LINEUP и т. п.). Старшее слово параметра lParam содержит значение позиции полосы просмотра.