Выполнение отложенной записи
Сам по себе процесс выполнения отложенной записи предельно прост: достаточно открыть и очистить Clipboard, вызвать функцию SetClipboardData, указав в первом параметре формат данных, а во втором - значение NULL, и закрыть Clipboard. Так, отложенная запись текстовых данных выглядит следующим образом:
OpenClipboard(hwnd); EmptyClipboard(); SetClipboardData(CF_TEXT, NULL); CloseClipboard();
Выполняя отложенную запись данных в Clipboard, приложение как бы объявляет, что оно способно "по первому требованию" других приложений предоставить данные в указанном формате. Сами данные на момент объявления могут не существовать.
Как только какое-либо приложение попытается прочитать записанные подобным образом данные, Windows обнаружит, что данных нет в памяти, так как для идентификатора соответствующего блока памяти указано значение NULL. В этом случае приложение, выполнившее отложенную запись, получит сообщение WM_RENDERFORMAT, в ответ на которое оно должно выполнить реальную запись данных.
Параметр wParam сообщения WM_RENDERFORMAT содержит код формата данных, который потребовался приложению, выполняющему чтение данных из Clipboard.
Обработчик сообщения WM_RENDERFORMAT должен, не открывая и не очищая Clipboard, предоставить данные в нужном формате, вызвав функцию SetClipboardData. На этот раз необходимо указать реальный идентификатор незафиксированного блока памяти, содержащего копируемые данные:
SetClipboardData(wParam, hglbTextCopyBuf);
После выполнения операции не следует закрывать Clipboard.
Теперь рассмотрим следующую ситуацию. Пусть пользователь скопировал данные из приложения в Clipboard с использованием отложенной записи, а затем попытался закрыть это приложение, и пусть в момент копирования не было активно ни одно окно динамического просмотра Clipboard.
В данной ситуации данные объявлены, но реально их нет в памяти. Следовательно, перед завершением приложения требуется выполнить запись данных в Clipboard во всех возможных форматах.
Если приложение объявило форматы данных в Clipboard, "взяв на себя обязательство" обеспечить их в случае необходимости, оно не может уйти со сцены, не выполнив реальной записи данных, так как в противном случае записывать объявленные данные будет некому.
Эта проблема имеет простое решение. Перед завершением работы приложение, объявившее в Clipboard данные, но не предоставившее их, получит от Windows сообщение WM_RENDERALLFORMATS. В ответ на это сообщение оно должно выполнить реальную запись данных.
Вот возможная реализация обработчика сообщения WM_RENDERALLFORMATS:
case WM_RENDERALLFORMATS: { OpenClipboard(hwnd); EmptyClipboard(); SendMessage(hwnd, WM_RENDERFORMAT, CF_TEXT, 0L); SendMessage(hwnd, WM_RENDERFORMAT, CF_BITMAP, 0L); SendMessage(hwnd, WM_RENDERFORMAT, CF_PALETTE, 0L); CloseClipboard(); return 0; }
Приложение несколько раз посылает само себе сообщение WM_RENDERFORMAT, указывая все возможные для него форматы данных. При этом обработчик сообщения WM_RENDERFORMAT каждый раз будет выполнять реальную запись данных в Clipboard.
Возможна такая ситуация, когда приложение выполнило отложенную запись и затем предоставила реальные данные, заказав для их хранения блок глобальной памяти, а другое приложение вскоре после этого очистило Clipboard и записало туда свои данные. Теперь первое приложение хранит в глобальной памяти никому не нужные данные, которые могут занимать много места.
В указанной ситуации ваше приложение получит сообщение WM_DESTROYCLIPBOARD. Обработчик этого сообщения может уничтожить ненужный блок памяти.