На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
! Правила раздела FAQ в группе разделов С++.
1. Раздел FAQ предназначен для публикации готовых статей.
2. Здесь нельзя задавать вопросы, для этого существуют соответствующие разделы:
Чистый С++
Visual C++ / MFC / WTL / WinApi
Borland C++ Builder
COM / DCOM / ActiveX / ATL
Сопутствующие вопросы
3. Внимание, все темы и сообщения в разделе премодерируются. Любое сообщение или тема будут видны остальным участникам только после одобрения модератора.
Модераторы: B.V., Qraizer
  
> Работа с буфером обмена (clipboard)
    Содержание:
    • Введение.
    • 1. Простейшие приемы работы с буфером обмена.
    • 2. Нестандартные форматы данных буфера обмена.
    • 3. Функции для работы с буфером обмена.
    • 4. Демонстрационное приложение.
    • 5. Ссылки.

    Очень часто в программах имеется набор функций для работы с буфером обмена, будь то текстовые редакторы или графические, поскольку с использованием буфера обмена упрощается обмен данными между программами. На форуме часто задают вопросы о том, как поместить изображение или текст в буфер обмена и потом извлечь эти данные, следовательно, в этой статье речь пойдет именно об этом.

    1. Простейшие приемы работы с буфером обмена.

    Прежде чем поместить в буфер обмена какую-либо информацию, ваша программа (далее просто окно) должна его открыть, используя функцию OpenClipboard. Однако следует учесть тот факт, что одновременно только одно окно может открыть буфер обмена. Следую хорошему тону программирования - если мы что-либо открыли, то нужно и закрыть. Работа с буфером обмена не является исключением для этого правила, следовательно, когда окно закончит работу, оно должно закрыть буфер обмена, вызвав функцию CloseClipboard.

    После того как программа открыла буфер обмена, она должна его очистить от предыдущего содержания, для чего следует вызвать функцию EmptyClipboard. В обязанности этой функции входит посылка сообщения WM_DESTROYCLIPBOARD предыдущему владельцу буфера обмена, освобождение ресурсов, связанных с данными в буфере обмена. После этих операций данная функция передает в монопольное использование буфер обмена окну, которое вызвало функцию OpenClipboard.

    После того как мы открыли буфер обмена и очистили его, мы имеем полное право помещать в него свои данные в различных форматах, используя функцию SetClipboardData (см. описание функции для описания стандартных форматов данных).

    Чтобы извлечь информацию из буфера обмена, окно должно вызвать функцию GetClipboardData.
    Данная функция в качестве параметра принимает формат буфера обмена, для того чтобы извлечь данные в этом формате. Если в буфер обмена данные поместила другая программа, вы можете проверить доступные форматы данных перед их непосредственным извлечением, используя функцию IsClipboardFormatAvailable.

    Полученную теоретическую информацию следует применить на практике. Ниже приведены примеры работы с буфером обмена, в качестве форматов данных будет использован текст и изображение, поскольку работа с буфером обмена является типичной для любого формата данных, разница лишь в способе формирования исходных данных.

    Пример записи и чтения текста.
    ExpandedWrap disabled
      CString source; //в эту переменную нужно записать текст, который в дальнейшем поместится в буфер обмена
      //запись текста в буфер обмена
      if(OpenClipboard())//открываем буфер обмена
      {
         HGLOBAL hgBuffer;
         char* chBuffer;
         EmptyClipboard(); //очищаем буфер
         hgBuffer= GlobalAlloc(GMEM_DDESHARE, source.GetLength()+1);//выделяем память
         chBuffer= (char*)GlobalLock(hgBuffer); //блокируем память
         strcpy(chBuffer, LPCSTR(source));
         GlobalUnlock(hgBuffer);//разблокируем память
         SetClipboardData(CF_TEXT, hgBuffer);//помещаем текст в буфер обмена
         CloseClipboard(); //закрываем буфер обмена
      }
       
      //чтение текста из буфера обмена
      CString fromClipboard;//в эту переменную сохраним текст из буфера обмена
      if ( OpenClipboard() )//открываем буфер обмена
      {
         HANDLE hData = GetClipboardData(CF_TEXT);//извлекаем текст из буфера обмена
         char* chBuffer= (char*)GlobalLock(hData);//блокируем память
         fromClipboard = chBuffer;
         GlobalUnlock(hData);//разблокируем память
         CloseClipboard();//закрываем буфер обмена
      }


    Пример записи и чтения изображения (bitmap).
    ExpandedWrap disabled
      //запись изображения в буфер обмена
      if ( OpenClipboard() )//открываем буфер обмена
      {
         EmptyClipboard(); //очищаем буфер
         //подготовим изображение для буфера обмена
         //в качестве изображения поместим снимок рабочего стола
         CDC memDC, dc;
       
         HWND hwnd = ::GetDesktopWindow();
         HDC hdc = ::GetWindowDC(hwnd);
       
         dc.Attach(hdc);
         memDC.CreateCompatibleDC(&dc);
       
         CBitmap bm;
         CRect rect;
       
         ::GetWindowRect(hwnd, &rect);
         CSize sz(rect.Width(), rect.Height());
       
         bm.CreateCompatibleBitmap(&dc, sz.cx, sz.cy);
         CBitmap* oldbm = memDC.SelectObject(&bm);
         memDC.BitBlt(0, 0, sz.cx, sz.cy, &dc, 0, 0, SRCCOPY);
       
         //помещаем данные в буфер обмена
         SetClipboardData(CF_BITMAP, bm.m_hObject);
         CloseClipboard(); //закрываем буфер обмена
       
         memDC.SelectObject(oldbm);
         ::ReleaseDC(hwnd, dc.Detach());
       
      }
       
      //чтение изображения из буфера обмена
      if ( OpenClipboard() )//открываем буфер обмена
      {
         //извлекаем данные из буфера обмена
         HBITMAP handle = (HBITMAP)GetClipboardData(CF_BITMAP);
         CBitmap * bm = CBitmap::FromHandle(handle);
       
         //отображаем данные из буфера
         BITMAP bit;
         bm->GetBitmap(&bit);
         CClientDC cdc(this);
         CDC dc;
         dc.CreateCompatibleDC(&cdc);
         dc.SelectObject(bm);
         cdc.BitBlt(0, 0, bit.bmWidth, bit.bmHeight, &dc, 0, 0, SRCCOPY);
       
         CloseClipboard();//закрываем буфер обмена
      }


    Подводя итог этого раздела можно выделить следующие основные шаги для записи и чтения данных при работе с буфером обмена. Для того чтобы записать данные в буфер обмена, вы должны выполнить следующую последовательность действий:
    • Открыть буфер обмена функцией OpenClipboard
    • Очистить содержимое буфера обмена функцией EmptyClipboard
    • Заказать функцией GlobalAlloc глобальный блок памяти, имеющий размер, достаточный для размещения записываемых в буфер обмена данных
    • Заблокировать полученный блок памяти функцией GlobalLock
    • Записать в заблокированный блок памяти данные
    • Разблокировать блок памяти функцией GlobalUnlock
    • Поместить данные в буфер обмена функцией SetClipboardData
    • Закрыть буфер обмена функцией CloseClipboard

    Процедура чтения данных из буфера обмена тоже проста. Приложение должно сделать следующее:
    • Открыть буфер обмена функцией OpenClipboard
    • Вызвать функцию GetClipboardData
    • Заблокировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalLock
    • Переписать данные из заблокированного буфера данных Clipboard в буфер, заказанный специально для этого приложением
    • Разблокировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalUnlock
    • Закрыть буфер обмена функцией CloseClipboard

    2. Нестандартные форматы данных буфера обмена.

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

    Для того чтобы зарегистрировать новый формат буфера обмена, используйте функцию RegisterClipboardFormat. Рассмотрим простой пример использования этой функции:

    ExpandedWrap disabled
      //объявим некую структуру
      struct MyClipboardData
      {
         CString strName;
         int     nAge;
      };
      //помещаем данные в буфер обмена
      UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT"); //регистрируем наш формат данных
      if(OpenClipboard())//для работы с буфером обмена его нужно открыть
      {
         //заполним нашу структуру данными
         MyClipboardData data;
         data.strName = "Vasya_Pupkin";
         data.nAge = 25;
       
         HGLOBAL hgBuffer;
         EmptyClipboard(); //очищаем буфер
         hgBuffer= GlobalAlloc(GMEM_DDESHARE, sizeof(MyClipboardData));//выделим память
         MyClipboardData* buffer = (MyClipboardData*)GlobalLock(hgBuffer);
         //запишем данные в память
         *buffer = data;
         //поместим данные в буфер обмена
         GlobalUnlock(hgBuffer);
         SetClipboardData(format, hgBuffer); //помещаем данные в буфер обмена
         CloseClipboard();//после работы с буфером, его нужно закрыть
      }
       
      //прочитаем наши данные из буфера обмена
      //вызываем второй раз, чтобы просто получить формат
      UINT format = RegisterClipboardFormat("MY_CUSTOM_FORMAT");
      MyClipboardData data;
      if ( OpenClipboard() )
      {
         //извлекаем данные из буфера
         HANDLE hData = GetClipboardData(format);
         MyClipboardData* buffer = (MyClipboardData*)GlobalLock( hData );
       
         //заполняем нашу структуру полученными данными
         data = *buffer;
       
         GlobalUnlock( hData );
         CloseClipboard();
      }


    Два различных приложения или две копии одного приложения могут зарегистрировать формат с одним и тем же именем, при этом функция RegisterClipboardFormat вернет один и тот же идентификатор формата. Поэтому два приложения всегда смогут "договориться", если они знают имя нестандартного формата данных.


    3. Функции для работы с буфером обмена.

    Функция ChangeClipboardChain:

    Данная функция удаляет определяемое окно просмотра буфера обмена из цепочки окон просмотра буфера обмена. Что это значит? А значит это следующее: чтобы получать сообщения от буфера обмена, наша программа должна заявить операционной системе об этом, вызвав функцию SetClipboardViewer , и если вдруг настанет такой момент, когда мы больше не хотим получать сообщения от буфера обмена (например: закрытие приложения), мы должны вызвать данную функцию.

    ExpandedWrap disabled
      BOOL ChangeClipboardChain
      (
          HWND hWndRemove,        // дескриптор удаляемого окна
          HWND hWndNewNext        // дескриптор следующего окна
      );


    В качестве параметров данная функция принимает дескрипторы окон: hWndRemove - идентифицирует окно, которое будет удалено из цепочки; hWndNewNext - дескриптор окна, которое следует за hWndRemove окном в цепочке окон просмотра буфера обмена, т.е. дескриптор, возвращенный ранее функцией SetClipboardViewer.

    После вызова данной функции, всем окнам в цепочке окон просмотра буфера обмена будет послано сообщение WM_CHANGECBCHAIN. Обработав данное сообщение окно обычно возвращает FALSE, следовательно, данная функция обычно будет возвращать FALSE. Однако если имеется только одно окно в цепочке, возвращаемое значение - обычно TRUE.

    Следует также отметить, что окно, идентифицированное как hWndNewNext, заменяет hWndRemove окно в цепочке.

    Функция CloseClipboard:

    Данная функция закрывает буфер обмена.

    ExpandedWrap disabled
      BOOL CloseClipboard(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения возвращаемое значение будет отлично от нуля, в противном случае - ноль. Для более подробной информации об ошибке следует вызвать функцию GetLastError.

    Слудеут отметить, что окно должно всегда вызывать данную функцию после окончания работы с буфером обмена. Если этого не сделать, другие окна не будут иметь доступ к буферу обмена, что не очень хорошо. Также следует учесть, что после вызова этой функции не следует помещать данные в буфер обмена.

    Функция CountClipboardFormats:

    Данная функция возвращает число различных форматов данных в текущем буфере обмена.

    ExpandedWrap disabled
      int CountClipboardFormats(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения функции, возвращаемое значение - это число различных форматов данных в текущем буфере обмена, в противном случае - ноль. Для более подробной информации об ошибке следует вызвать функцию GetLastError.

    Функция EmptyClipboard:

    Данная функция очищает буфер обмена и освобождает дескрипторы данных в нем. Затем функция назначает монопольное использование буфера обмена окну, которое вызвало функцию OpenClipboard.

    ExpandedWrap disabled
      BOOL EmptyClipboard(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения возвращаемое значение будет отлично от нуля, в противном случае - ноль. Для более подробной информации об ошибке следует вызвать функцию GetLastError.

    Следует отметить, что перед вызовом данной функции, прикладная программа должна открыть буфер обмена, используя функцию OpenClipboard. Если приложение при открытии буфера обмена определяет дескриптор окна NULL, EmptyClipboard завершается успешно, но устанавливает владельца буфера обмена как NULL.

    Функция EnumClipboardFormats:

    Данная функция позволяет перечислять форматы данных, которые являются в настоящее время доступными в буфере обмена. Чтобы выполнить перечисление всех форматов данных буфера обмена необходимо произвести ряд обращений к этой функции. Для каждого обращения, параметр формата определяет доступный формат буфера обмена, а функция возвращает значение следующего доступного формата буфера обмена.

    ExpandedWrap disabled
      UINT EnumClipboardFormats
      (
          UINT format     // Определяет известный доступный формат буфера обмена
      );


    В качестве входного параметра данная функция принимает идентификатор формата данных буфера обмена. format - определяет формат буфера обмена, о котором известно, что он является доступным. Для того чтобы начать перечисление форматов буфера обмена, нужно установить format в 0, тогда функция возвращает первый доступный формат буфера обмена. При последующих вызовах, во время перечисления, в format устанавливается результат предыдущего обращения к EnumClipboardFormat.

    В случае успешного завершения, возвращаемое значение - формат буфера обмена, который следует за заданным форматом, иными словами, следующий доступный формат буфера обмена. В случае завершения с ошибкой, возвращаемое значение 0. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError. Следует отметить, что если буфер обмена не открыт, функция завершается с ошибкой.

    При перечислении форматов данных следует помнить, что если больше нет форматов буфера обмена, при вызове данной функции, возвращаемое значение будет равно 0. Однако, функция GetLastError возвращает значение NO_ERROR. Это позволяет делать различие между завершением с ошибкой и концом операции перечисления.

    Следует отметить, что перед перечислением форматов буфера обмена, необходимо открыть его. Чтобы открыть буфер обмена, используйте функцию OpenClipboard. Данная функция перечисляет форматы по порядку, как они были помещены в буфер обмена.

    Важно и то, что для некоторых форматов буфера обмена, операционная система обеспечивает автоматическое преобразование форматов. В таком случае, эта функция перечисляет заданный формат, затем перечисляет форматы, в которые он может быть преобразован.

    Небольшой пример использования данной функции, чтобы наглядно показать все описанное выше:

    ExpandedWrap disabled
      if (OpenClipboard())
      {
         UINT uFormat = EnumClipboardFormats(0); //получаем первый доступный
       
          while (uFormat)
          {
              //тут можно что-либо делать
              ...
        
              uFormat = EnumClipboardFormats(uFormat); //берем следующий формат
          }
          CloseClipboard();
      }


    Функция GetClipboardData:

    Данная функция извлекает данные из буфера обмена в заданном формате. Предварительно необходимо открыть буфер обмена.

    ExpandedWrap disabled
      HANDLE GetClipboardData
      (
          UINT uFormat    // формат буфера обмена
      );


    В качестве параметра uFormat функция принимает идентификатор формата, данные в котором необходимо извлечь из буфера обмена.

    В случае успешного завершения данной функции, возвращаемое значение - дескриптор объекта буфера обмена в заданном формате, в противном случае - возвращаемое значение NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Следует отметить, что при вызове данной функции операционная система выполнит скрытое преобразование форматов данных. Таблица преобразования форматов:

    ExpandedWrap disabled
      Формат Буфера обмена     Формат преобразования     Платформа поддержки
       
      CF_BITMAP                CF_DIB                    Windows NT/2000, Windows 95/98
      CF_BITMAP                CF_DIBV5                  Windows 2000
      CF_DIB                   CF_BITMAP                 Windows NT/2000, Windows 95/98
      CF_DIB                   CF_PALETTE                Windows NT/2000, Windows 95/98
      CF_DIB                   CF_DIBV5                  Windows 2000
      CF_DIBV5                 CF_BITMAP                 Windows 2000
      CF_DIBV5                 CF_DIB                    Windows 2000
      CF_DIBV5                 CF_PALETTE                Windows 2000
      CF_ENHMETAFILE           CF_METAFILEPICT           Windows NT/2000, Windows 95/98
      CF_METAFILEPICT          CF_ENHMETAFILE            Windows NT/2000, Windows 95/98
      CF_OEMTEXT               CF_TEXT                   Windows NT/2000, Windows 95/98
      CF_OEMTEXT               CF_UNICODETEXT            Windows NT/2000
      CF_TEXT                  CF_OEMTEXT                Windows NT/2000, Windows 95/98
      CF_TEXT                  CF_UNICODETEXT            Windows NT/2000
      CF_UNICODETEXT           CF_OEMTEXT                Windows NT/2000
      CF_UNICODETEXT           CF_TEXT                   Windows NT/2000


    Функция GetClipboardFormatName:

    Данная функция извлекает из буфера обмена имя заданного зарегистрированного формата. Функция копирует имя в заданный буфер.

    ExpandedWrap disabled
      int GetClipboardFormatName
      (
          UINT format,        // формат буфера обмена
          LPTSTR lpszFormatName,  // адрес буфера для имени
          int cchMaxCount         //длина строки имени в символах
      );


    В качестве входных параметров данная функция получает идентификатор формата данных буфера обмена (format), адрес буфера для названия формата (lpszFormatName) и длину буфера (cchMaxCount). Идентификатор формата lpszFormatName определяет тип формата, название которого будет извлечено. Этот параметр не должен определять какой-либо из предопределенных форматов буфера обмена. lpszFormatName - указывает на буфер, который должен принять имя формата; cchMaxCount - определяет максимальную длину строки (в символах), которая будет скопирована в буфер. Следует учесть, что если имя превышает это ограничение, оно усекается.

    В случае успешного завершения, возвращаемое значение - длина строки (в символах), скопированной в буфер, в противном случае, возвращаемое значение равно 0, указывая, что запрошенный формат не существует или предопределен. Чтобы получать дополнительные данные об ошибке, вызовите функцию GetLastError.

    Функция GetClipboardOwner:

    Данная функция извлекает дескриптор окна текущего владельца буфера обмена.

    ExpandedWrap disabled
      HWND GetClipboardOwner(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения, возвращаемое значение - дескриптор окна, которое является в данный момент владельцем буфера обмена. В противном случае, возвращаемое значение NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Следует отметить, что буфер обмена может содержать данные, даже если у него в настоящее время нет владельца (владельцем буфера обмена называется окно, которое последним поместило данные в буфере обмена).

    Функция GetClipboardViewer:

    Данная функция извлекает дескриптор первого окна в цепочке окон просмотра буфера обмена.

    ExpandedWrap disabled
      HWND GetClipboardViewer(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения, возвращаемое значение - дескриптор первого окна в цепочке окон просмотра буфера обмена. Если же не определено ни одно окно просмотра буфера обмена, возвращаемое значение NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Функция GetOpenClipboardWindow:

    Данная функция извлекает дескриптор окна, которое в настоящее время имеет открытый буфер обмена.

    ExpandedWrap disabled
      HWND GetOpenClipboardWindow(VOID)


    Данная функция не имеет входных параметров. В случае успешного завершения, возвращаемое значение - дескриптор окна, которое имеет открытый буфер обмена. Если нет окна, которое открыло буфера обмена, возвращаемое значение NULL, т.е. если открыть буфер обмена и не передать в функцию OpenClipboard дескриптор окна, бефер будет открыт, но не связан с каким-либо окном. В таком случае данная функция вернет NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Функция GetPriorityClipboardFormat:

    Данная функция возвращает значение первого доступного формата буфера обмена в заданном списке.

    ExpandedWrap disabled
      int GetPriorityClipboardFormat
      (
          UINT *paFormatPriorityList, // адрес списка приоритетов
          int cFormats        // число вводимых данных в списке
      );


    В качестве входных параметров данная функция принимает массив целых чисел без знака, идентифицирующих форматы буфера обмена (paFormatPriorityList) и число введенных данных в массиве paFormatPriorityList (cFormats). Следует учесть, что cFormats не должно быть больше, чем число вводимых данных в списке.

    В случае успешного завершения, возвращаемое значение - первый формат буфера обмена в списке, для которого данные являются доступными. Данная функция вернет NULL, если буфер обмена пуст, или -1 (-1) - если буфер обмена содержит данные, но не в каком-либо из заданных форматов. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Функция IsClipboardFormatAvailable:

    Данная функция определяет, содержит ли буфер обмена данные в заданном формате.

    ExpandedWrap disabled
      BOOL IsClipboardFormatAvailable
      (
          UINT format     // формат буфера обмена
      );


    В качестве входного параметра данной функции является идентификатор формата данных (format).

    Если формат буфера обмена доступен, возвращаемое значение не 0, в противном случае функция вернет 0. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    В качестве совета могу сказать, что всегда следует использовать данную функцию перед извлечением данных из буфера обмена, дабы избежать ошибок.

    Функция OpenClipboard:

    Данная функция открывает буфер обмена для работы с ним и препятствует другим прикладным программам изменять содержимое буфера обмена.

    ExpandedWrap disabled
      BOOL OpenClipboard
      (
          HWND hWndNewOwner       // дескриптор окна, открывшего буфер обмена
      );


    В качестве входных параметров данная функция принимает дескриптор окна (hWndNewOwner). Этот дескриптор идентифицирует окно, которое будет связано с открытым буфером обмена. Однако можно не задавать этот дескриптор, в таком случае, открытый буфер обмена будет связан с текущей задачей.

    В случае успешного завершения данной функции, возвращается значение отличное от 0, в противном случае, возвращаемое значение 0. Чтобы получить дополнительные данные об ошибках, обратитесь к функции GetLastError.

    Следует учесть, что если другая программа открыла буфер обмена для работы с ним, данная функция завершится с ошибкой. Важным моментом является то, что окно, идентифицированное параметром hWndNewOwner, не станет владельцем буфера обмена, если не было обращения к функции EmptyClipboard.

    Функция RegisterClipboardFormat:

    Данная функция регистрирует новый формат буфера обмена, который можно будет использовать в дальнейшем для работы.

    ExpandedWrap disabled
      UINT RegisterClipboardFormat
      (
          LPCTSTR lpszFormat      // адрес строки с именем
      );


    В качестве входного параметра этой функции (lpszFormat) служит адрес строки, которая именует новый формат.

    В случае успешного завершения, возвращаемое значение идентифицирует зарегистрированный формат буфера обмена, в противном случае функция возвращает 0. Чтобы получать дополнительные данные об ошибке, вызовите функцию GetLastError.

    Следует учесть, что если формат данных с заданным именем уже существует, новый формат не регистрируется, а возвращаемое значение идентифицирует существующий формат. Это дает возможность больше чем одной прикладной программе работать с буфером обмена, используя тот же самый зарегистрированный формат буфера обмена. Обратите внимание, что сравнение названия формата осуществляется без учета регистра.

    Функция SetClipboardData:

    Данная функция помещает данные в буфер обмена в заданном формате.

    ExpandedWrap disabled
      HANDLE SetClipboardData
      (
          UINT uFormat,       // формат буфера обмена
          HANDLE hMem     // дескриптор данных
      );


    В качестве входных параметров данная функция принимает формат буфера обмена (uFormat) и дескриптор данных (hMem). В качестве формата буфера обмена функция может принимать любой из зарегистрированных или стандартных форматов буфера обмена; hMem - идентифицирует данные в заданном формате.

    В случае успешного завершения, возвращаемое значение - дескриптор данных, в противном случае - NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Ниже приведен список стандартных форматов данных буфера обмена с описанием, которые может принимать uFormat:
    • CF_BITMAP - Дескриптор к точечному рисунку (HBITMAP).
    • CF_DIB - Объект в памяти содержит структуру BITMAPINFO, сопровождаемую растровыми битами.
    • CF_DIF - Формат обмена данными программы Arts'.
    • CF_DSPBITMAP - Растровый формат отображения данных на дисплее, связанный с собственным форматом. Параметр hMem должен быть дескриптором данных, которые могут отображаться в растровом формате вместо частным образом форматируемых данных.
    • CF_DSPENHMETAFILE - Формат отображения улучшенного метафайла связанного с собственным форматом. Параметр hMem должен быть дескриптор данных, которые могут отображаться в улучшеннном формате метафайла вместо частным образом форматируемых данных.
    • CF_DSPMETAFILEPICT - Формат отображения данных метафайла-картинки, связанного с собственным форматом. Параметр hMem должен быть дескриптором данных, которые могут отображаться в формате метафайла-картинки вместо частным образом форматируемых данных.
    • CF_DSPTEXT - Формат отображения текста, связанный с собственным форматом. Параметр hMem должен быть дескриптором данных, которые могут отображаться в текстовом формате вместо частным образом форматируемых данных.
    • CF_ENHMETAFILE - Дескриптор улучшенного метафайла (HENHMETAFILE).
    • От CF_GDIOBJFIRST до CF_GDIOBJLAST - Диапазон целочисленных значений для определяемых программой форматов буфера обмена объекта GDI. Дескрипторы, связанные с форматами буфера обмена в этом диапазоне автоматически не удаляются, при использовании функции GlobalFree, когда очищается буфер обмена. Также, при использовании значений в этом диапазоне, параметр hMem - не дескриптор к объекту GDI, а дескриптор, помещенный функцией GlobalAlloc с флажками GMEM_MOVEABLE и GMEM_DDESHARE.
    • CF_HDROP - Дескриптор типа HDROP - это тот, который идентифицирует список файлов. Прикладная программа может извлечь информацию о файлах, передавая дескриптор функции DragQueryFile.
    • CF_LOCALE - Данные являются дескриптором локального идентификатора, связанного с текстом в буфере обмена. Когда вы закрываете буфер обмена, если он содержит данные CF_TEXT, а не данные CF_LOCALE, система автоматически устанавливает формат CF_LOCALE в текущем месте ввода информации. Вы можете использовать формат CF_LOCALE, чтобы сопоставлять различные места действия с текстом буфера обмена. Прикладная программа, которая вставляет текст из буфера обмена, может извлечь этот формат, чтобы определить, какой набор символов использовался, чтобы создать текст. Обратите внимание, что буфер обмена не поддерживает обычный текст в многокомпонентных наборах символов. Чтобы добиться этого, взамен используйте форматированный текстовый тип данных, такой как RTF. Windows NT: система использует кодовую страницу, связанную с CF_LOCALE, чтобы неявно преобразовать из CF_TEXT в CF_UNICODETEXT. Следовательно, правильная таблица кодовой страницы используется для преобразования.
    • CF_METAFILEPICT - Дескриптор метафайла изображает формат как определено структурой METAFILEPICT. При передаче дескриптора CF_METAFILEPICT посредством динамического обмена данными (прямой ввод данных (DDE)), прикладная программа, ответственная за удаление hMem должна также освободить метафайл, упоминаемый дескриптором CF_METAFILEPICT.
    • CF_OEMTEXT - Текстовый формат, содержащий символы в OEM наборе символов. Каждые строка заканчивается комбинацией возврат каретки / перевод строки (carriage return/linefeed)(CR-LF). Символ пробела сообщает о конце данных.
    • CF_OWNERDISPLAY - Собственный формат отображения данных. Владелец буфера обмена должен отображать, и модифицировать окна просмотра буфера обмена, и принимать сообщения WM_ASKCBFORMATNAME, WM_HSCROLLCLIPBOARD, WM_PAINTCLIPBOARD, WM_SIZECLIPBOARD и WM_VSCROLLCLIPBOARD. Параметр hMem должен иметь значение NULL.
    • CF_PALETTE - Дескриптор цветовой палитры. Всякий раз, когда прикладная программа помещает данные в буфер обмена, которые зависят от цветовой палитры или назначает цветовую палитру, она должна поместить в буфер обмена также и палитру. Если буфер обмена содержит данные в формате CF_PALETTE (логическая цветовая палитра), прикладная программа должна использовать функции SelectPalette и RealizePalette, чтобы реализовать (сравнить) любые другие данные в буфере обмена в зависимости от этой логической палитры. При отображении данных буфера обмена, буфер обмена Windows всегда использует как свою текущую палитру любого объекта в буфере обмена, который находится в формате CF_PALETTE.
    • CF_PENDATA - Дополнительные данные для пера в Microsoft Windows для Pen Computing (Компьютерного пера).
    • От CF_PRIVATEFIRST до CF_PRIVATELAST - Диапазон целых значений для собственных форматов буфера обмена. Дескрипторы, связанные с собственными форматами буфера обмена автоматически не освобождаются; владелец буфера обмена должен освобождать такие дескрипторы, обычно в ответ на сообщение WM_DESTROYCLIPBOARD.
    • CF_RIFF - Представляет звуковые данные более сложные, чем они могут быть представлены в стандартном звуковом формате CF_WAVE.
    • CF_SYLK - Формат Символической Связи Microsoft (SYLK) (Microsoft Symbolic Link).
    • CF_TEXT - Текстовый формат. Каждая строка оканчивается комбинацией возврата каретки / перевода строки (CR-LF). Символ пробела сообщает о конце данных. Используйте этот формат для текста ANSI.
    • CF_WAVE - Представляет звуковые данные в одном из стандартных звуковых форматах, таких как импульсно-кодовой модуляции 11 кГц или 22 кГц (ИКМ) (PCM- pulse code modulation).
    • CF_TIFF - Формат Файла Тегированного Изображения (TIFF - Tagged-image file format).
    • CF_UNICODETEXT - Только Windows NT: Формат текста Юникода. Каждая строка оканчивается комбинацией возврата каретки / перевода строки (CR-LF). Символ пробела сообщает о конце данных.

    При работе с буфером обмена следует учитывать, что операционная система выполняет неявные преобразования формата данных между некоторыми форматами буфера обмена, когда прикладная программа вызывает функцию GetClipboardData. За дополнительной информацией см. функцию GetClipboardData.

    Функция SetClipboardViewer:

    Данная функция добавляет определяемое окно к цепочке окон просмотра буфера обмена.

    ExpandedWrap disabled
      HWND SetClipboardViewer
      (
          HWND hWndNewViewer      // дескриптор окна просмотра буфера обмена
      );


    В качестве входного параметра данной функции служит дескриптор окна (hWndNewViewer), идентифицирующий окно, которое будет добавлено к цепочке окон буфера обмена.

    В случае успешного завершения, возвращаемое значение идентифицирует следующее окно в цепочке окон просмотра буфера обмена, однако если происходит ошибка или не имеется никаких других окон в цепочке окон просмотра буфера обмена, возвращаемое значение NULL. Чтобы получить дополнительные данные об ошибке, вызовите функцию GetLastError.

    Следует отметить, что если окно является частью цепочки окон просмотра буфера обмена, оно должно обрабатывать сообщения WM_CHANGECBCHAIN и WM_DRAWCLIPBOARD, а также, удаляться из цепочки окон просмотра, вызовом функции ChangeClipboardChain - например, в ответ на сообщение WM_DESTROY.

    4. Демонстрационное приложение.

    В прикрепленном архиве содержится проект, который демонстрируют работу с буфером обмена.

    5. Ссылки.

    www.firststeps.ru
    www.rsdn.ru

    6. Ключевые слова.

    ChangeClipboardChain, CloseClipboard, CountClipboardFormats, EmptyClipboard, EnumClipboardFormats, GetClipboardData, GetClipboardFormatName, GetClipboardOwner, GetClipboardViewer, GetOpenClipboardWindow, GetPriorityClipboardFormat, IsClipboardFormatAvailable, OpenClipboard, RegisterClipboardFormat, SetClipboardData, SetClipboardViewer.
    Сообщение отредактировано: B.V. -

    Прикреплённый файлПрикреплённый файлClipDemo.rar (53.19 Кбайт, скачиваний: 643)
      Копируем список файлов в буфер Windows
      ExpandedWrap disabled
        #define NO_WIN32_LEAN_AND_MEAN
        #include <vector>
        #include <string>
        using namespace std;
         
        bool CopyFilesToClipboard(vector <string> &ListFile)
        {
           vector<string>::iterator It;
           //открываем буфер
           if(!OpenClipboard(Application->Handle)) return false;
           //очищаем буфер
           EmptyClipboard();
           //Определяем размер
           int SizeLine(1);
           for (It=ListFile.begin();It!=ListFile.end();++It)
              SizeLine+=(*It).length()+1;
           //Выделяем память
           HGLOBAL  hGlobal = GlobalAlloc(GMEM_SHARE|GMEM_MOVEABLE|GMEM_ZEROINIT,
                                                    sizeof(DROPFILES) + SizeLine);
           if (!hGlobal) return false;
           //Создаем структуру
           DROPFILES *MyDropFiles = (DROPFILES*)GlobalLock(hGlobal);
           //записываем данные в структуру
           SizeLine = MyDropFiles->pFiles = sizeof(DROPFILES);
           for (It=ListFile.begin();It!=ListFile.end();++It)
           {
              strcpy((char*)MyDropFiles + SizeLine, (*It).c_str());
              SizeLine+=(*It).length()+1;
           }
           GlobalUnlock(hGlobal);
           //записываем данные в буфер
           if (!SetClipboardData(CF_HDROP, hGlobal)) return false;
           //закрываем буфер
           CloseClipboard();
           return true;
        }

      Пример использования:
      ExpandedWrap disabled
           vector <string> ListFile;
           ListFile.push_back("C:\\Boot.ini");
           ListFile.push_back("C:\\NTDETECT.COM");
           ListFile.push_back("C:\\MSDOS.SYS");
           ListFile.push_back("C:\\AUTOEXEC.BAT");
           CopyFilesToClipboard(ListFile);
        Прога выводит имена файлов из буфера обмена

        ExpandedWrap disabled
          #include <stdlib.h>
          #include <windows.h>
           
          int main()
          {
              if (OpenClipboard(GetDesktopWindow())){
                  HANDLE hData = GetClipboardData (CF_HDROP);
                  if(hData>0){
                      int i,nBufSize=2;
                      for(i=0;nBufSize>1;i++){
                          nBufSize = DragQueryFile(hData, i, NULL, 0)+1;
                          if(nBufSize>1){
                              char *fName = (char*)malloc(nBufSize*sizeof(char));
                              DragQueryFile(hData, i, fName, nBufSize );
                              if(fName!=NULL){
                                  char * buf = (char*)malloc(strlen(fName)+1);
                                  CharToOem(fName, buf);
                                  printf("%s\n",buf);
                                  free(buf);
                              }
                          }
                      }
                  }
                  CloseClipboard();
              }
              return 0;
          }
        0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
        0 пользователей:


        Рейтинг@Mail.ru
        [ Script execution time: 0,0604 ]   [ 17 queries used ]   [ Generated: 19.04.24, 00:00 GMT ]