Копирование информации в Буфер обмена
В прикладной программе Метка, функция EditCopy, определяемая программой, копирует текущий выбор в буфер обмена. Эта функция делает следующее:
- Открывает буфер обмена путем вызова функции OpenClipboard.
- Очищает буфер обмена путем вызова функции EmptyClipboard.
- Вызывает функцию SetClipboardData для каждого формата буфера обмена, которыми обеспечена прикладная программа.
- Закрывает буфер обмена путем вызова функции 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;
}