3.13.3 - Копирование информации в Буфер обмена

В прикладной программе Метка, функция EditCopy, определяемая программой, копирует текущий выбор в буфер обмена. Эта функция делает следующее:

  1. Открывает буфер обмена путем вызова функции OpenClipboard.
  2. Очищает буфер обмена путем вызова функции EmptyClipboard.
  3. Вызывает функцию SetClipboardData для каждого формата буфера обмена, которыми обеспечена прикладная программа.
  4. Закрывает буфер обмена путем вызова функции CloseClipboard.

В зависимости от текущего выбора, функция EditCopy или копирует область текста, или копирует определяемую программой структуру, представляющую всю пометку. Структура, названная LABELBOX, определяется следующим образом.

#define BOX_ELLIPSE 0
#define BOX_RECT 1
#define CCH_MAXLABEL 80
#define CX_MARGIN 12

typedef struct tagLABELBOX {	// box (окно)
	RECT rcText;		// координаты прямоугольника, содержащего текст
	BOOL fSelected;		// ИСТИНА (TRUE), если выбрана пометка
	BOOL fEdit;		// ИСТИНА (TRUE), если выбран текст
	int nType;		// прямоугольный или эллиптический
	int ichCaret;		// позиция каретки
	int ichSel;		// с ichCaret, разграничивает выбор
	int nXCaret;		// позиция окна в соответствии с ichCaret
	int nXSel;		// позиция окна в соответствии с ichSel
	int cchLabel;		// длина текста в atchLabel
	TCHAR atchLabel[CCH_MAXLABEL];
} LABELBOX, *PLABELBOX;

Ниже следует функция EditCopy.

BOOL WINAPI EditCopy(VOID)
{
	PLABELBOX pbox;
	LPTSTR lptstrCopy;
	HGLOBAL hglbCopy;
	int ich1, ich2, cch;

	if (hwndSelected == NULL) return FALSE;

	// Открываем буфер обмена и очищаем его.

	if (!OpenClipboard(hwndMain))
		return FALSE;
	EmptyClipboard();

	// Получаем указатель на структуру для выбора пометки.

	pbox = (PLABELBOX) GetWindowLong(hwndSelected, 0);

	// Если текст выбран, он копируется с использованием формата CF_TEXT.
	if (pbox->fEdit)
	{
		if (pbox->ichSel == pbox->ichCaret)	// нулевая длина
		{
			CloseClipboard();		// выбор
			return FALSE;
		}
		if (pbox->ichSel < pbox->ichCaret)
		{
			ich1 = pbox->ichSel;
			ich2 = pbox->ichCaret;
		}
		else
		{
			ich1 = pbox->ichCaret;
			ich2 = pbox->ichSel;
		}
		cch = ich2 - ich1;

		// Распределяем глобальный объект памяти для текста.
		hglbCopy = GlobalAlloc(GMEM_DDESHARE,
			(cch + 1) * sizeof(TCHAR));
		if (hglbCopy == NULL)
		{
			CloseClipboard();
			return FALSE;
		}

		// Блокируем дескриптор и копируем текст в буфер.
		lptstrCopy = GlobalLock(hglbCopy);
		memcpy(lptstrCopy, &pbox->atchLabel[ich1],
			cch * sizeof(TCHAR));
		lptstrCopy[cch] = (TCHAR) 0;	// Символ пробела

		GlobalUnlock(hglbCopy);

		// Помещаем дескриптор в буфер обмена.
		SetClipboardData(CF_TEXT, hglbCopy);
	}
	// Если никакой текст не выбран, пометка скопирована как единое целое.
	else
	{
		// Сохраним скопированную пометку как локальный объект памяти.
		// Эта копирование используется для представления данных по запросу.
		// Оно освобождается в ответ на сообщение WM_DESTROYCLIPBOARD.

		pboxLocalClip = (PLABELBOX) LocalAlloc(
			LMEM_FIXED,
			sizeof(LABELBOX));

		if (pboxLocalClip == NULL)
		{
			CloseClipboard();
			return FALSE;
		}
		memcpy(pboxLocalClip, pbox, sizeof(LABELBOX));
		pboxLocalClip->fSelected = FALSE;
		pboxLocalClip->fEdit = FALSE;

		// Помещаем зарегистрированный формат, собственный формат
		// и формат CF_TEXT записи данных
		// в буфере обмена, используя отсроченную запись.
		SetClipboardData(uLabelFormat, NULL);
		SetClipboardData(CF_OWNERDISPLAY, NULL);
		SetClipboardData(CF_TEXT, NULL);
	}
	// Закроем буфер обмена.
	CloseClipboard();
	return TRUE;
}

Предыдущий Шаг | Следующий Шаг | Оглавление
Автор Владимир Соковиков.