Свойства выделяемого блока памяти




 

Макрос Значение
  GHND Блок может перемещаться и заполняется нулями
  GMEM_DDESHARE Память может использоваться для операций c буфером обмена
  GMEM_DISCARDABLE Память может быть выгружена
  GMEM_LOWER Память не перемещается
  GMEM_NOCOMPACT Блок может перемещаться в памяти
    Блок не может изменять размер при операциях сборки мусора
  GMEM_NODISCARD Блок не может быть выгружен
  GMEM_SHARE To же, что и GMEM_DDESHARE
  GMEM_ZEROINIT Выделенный блок памяти заполняется нулями
  GPTR Блок памяти не может перемещаться и заполняется нулями

 

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

Как уже упоминалось, функция GlobalAlloc() возвращает дескриптор, а не указа­тель на выделенную память. Для получения указателя на область памяти, выделенную при помощи GlobalAlloc(), следует использовать функцию GlobalLock():

 

LPVOID GlobalLock(HGLOBAL hObj);

 

Функция GlobalLock() фиксирует в памяти объект (блок), дескриптор которого передается в параметре hObj. Зафиксированный объект не перемещается в памяти и не выгружается. Функция GlobalLock() возвращает адрес начала блока в случае успешного завершения или NULL при возникновении ошибки. Чтобы осуществить обращение к глобальным блокам памяти, эти блоки нужно обязательно зафиксиро­вать. Таким образом, вызов функции GlobalLock() – это способ получения указателя на блок глобальной памяти. Фиксация блока также предохраняет память от обраще­ния к ней других программ, пока с этой памятью работает Ваша программа.

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

 

BOOL GlobalUnlock(HGLOBAL hObj);

 

Функция GlobalUnlock()возвращает нулевое значение в случае успешного завер­шения и ненулевое при возникновении ошибки. Дескриптор разблокируемого объек­та передается в параметре hObj.

После копирования данных в глобальный блок памяти нужно открыть буфер обмена при помощи вызова функции OpenClipboard():

 

BOOL OpenClipboard(HWND hWnd);

 

Функция OpenClipboard()разрешает вызывающей программе доступ к буферу обмена (т.е. открывает его). После того как программа открыла буфер обмена, другие приложения использовать его не могут. Функция возвращает ненулевое значение, если буфер обмена успешно открыт, и нуль, если в данный момент буфер открыть невозможно. Параметр hWnd задает дескриптор окна, открывающего буфер обмена.

Когда буфер обмена успешно открыт, приложение должно очистить буфер обмена, вызвав функцию EmptyClipboard():

 

BOOL EmptyClipboard(void);

 

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

Чтобы записать данные в буфер обмена, его следует настроить на память, содержа­щую эти данные. Это делается при помощи вызова функции SetClipboardData():

 

HANDLE SetClipboardData(UINT Format, HANDLE hData);

 

Функция SetClipboardData() настраивает буфер обмена на использование глобаль­ной памяти, дескриптор которой указывается в параметре hData. Она возвращает новый дескриптор памяти, на которую настроен буфер обмена, либо NULL в случае возникновения ошибки.

Формат данных, записываемых в буфер обмена, задается параметром Format. Этот параметр может принимать предопределенные значения из таблицы 13.5, либо задавать собственный формат данных пользователя.

 

Таблица 13.5

Форматы и типы данных

 

Формат Тип данных
  CF_BITMAP Растр (bitmap) в чистом виде
  CF_DIB Растр (bitmap) с заголовком BITMAPINFO
  CF_DIF Универсальный формат обмена (Data Interchange Format)
  CF_DSPBITMAP Пользовательское растровое изображение
  CF_DSPENHMETAFILE Пользовательский расширенный метафайл
  CF_DSPMETAFILEPICT Пользовательский метафайл
  CF_DSPTEXT Пользовательский текст
  С F_ENHMETAFILE Расширенный метафайл
  CF_METAFILEPICT Метафайл в стиле METAFILEPICT
  CF_OEMTEXT Текст в кодировке OEM
  CF_OWNERDISPLAY Пользовательский формат данных
  CF_PALETTE Цветовая палитра
  CF_PENDATA Формат для данных, связанных с электронным пером
  CF_RIFF Файл ресурсов (Resource Interchange File Format)
  CF_SYLK Символическая ссылка
  CF_TEXT Текст
  CF_TIFF Графика в формате TIFF
  CF_WAVE Звук в формате WAVE
  CF_UNICODETEXT Текст в кодировке UNICODE

 


Для форматов CF_TEXT, CF_OEMTEXT и CF_UNICODETEXT текстовые блоки должны заканчиваться нулевым символом, а строки – комбинацией CR/LF – «возврат каретки»/«новая строка». Значения в диапазоне от CF_PRTVATEFIRST до CF_PRIVATELAST резервируются для локальных пользовательских форматов данных, а значе­ния в диапазоне от CF_GDIOBJFIRST до CF_GDIOBJLAST – для пользовательских графических объектов.

После записи данных программа должна сразу же освободить буфер обмена при помощи функции CloseClipboard():

 

BOOL CloseClipboard (void);

 

Эта функция возвращает ненулевое значение в случае успешного завершения и нуль при возникновении ошибки.

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

1) открыть буфер обмена;

2) получить указатель на данные, записанные в буфер обмена;

3) скопировать данные из буфера обмена;

4) закрыть буфер обмена.

 

Перечисленные шаги выполняются в следующем фрагменте программы:

 

if(OpenClipboard(hwnd))

{

hGin=GetClipboardData(CF_TEXT);

p=(char*)GlobalLock(hGin);

//

// Операторы копирования данных

// из глобальной памяти

//

GlobalUnlock(hGin);

CloseClipboard();

}

 

Чтобы получить доступ к данным, хранящимся в буфере обмена, последний должен быть открыт. После этого нужно получить дескриптор глобальной памяти, в которой хранятся данные хбуфера обмена. Это делается при помощи функции GetClipboardData():

 

HANDLE GetClipboardData(UINT Format);

 

Функция GetClipboardData() возвращает дескриптор глобальной памяти, содер­жащей информацию в заданном формате. Требуемый формат данных задается в параметре Format. Если в буфере обмена к моменту запроса нет данных, имеющих требуемый формат, функция возвращает значение NULL. В приведенном фрагменте программы запрашиваемый формат данных CF_TEXT.Для получения указателя по дескриптору, возвращаемому функцией GetClipboardData(), используется функция GlobalLock(),описанная выше.

Теперь программа должна скопировать данные из памяти буфера обмена в собственный локальный буфер. Поскольку функция GetClipboardData()возвращает дескриптор памяти, на которую настроен буфер обмена, программа должна скопи­ровать данные до того, как управление будет возвращено Windows. Причину этого легко понять: после возврата управления Windows содержимое буфера обмена может быть изменено другим приложением.

 

Пример 13-3. Программа работы с буфером обмена Clipboard

 

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

 

// Демонстрация работы с буфером обмена Clipboard

#include <Windows.h>

#include <String.h>

#include "Clip.h"

#define Maxsize 100

 

LRESULT CALLBACK WindowFunc(HWND, UINT,

WPARAM, LPARAM);

char szWinName[]="МоеОкно"; // Имя класса окна

HGLOBAL hGout, hGin;

char text[]="Это текст для буфера обмена";

 

int WINAPI WinMain(HINSTANCE hThisInst,

HINSTANCE hPrevInst,

LPSTR lpszArgs,

int nWinMode)

{

HWND hwnd;

MSG msg;

HACCEL hAccel; // Для обработки акселераторов

WNDCLASS wcl; // Определить класс окна

wcl.hInstance=hThisInst; // Дескриптор приложения

wcl.lpszClassName=szWinName; // Имя класса окна

wcl.lpfnWndProc=WindowFunc; // Функция окна

wcl.style=0; // Стиль по умолчанию

wcl.hIcon=LoadIcon(NULL,IDI_APPLICATION); // Иконка

wcl.hCursor=LoadCursor(NULL,IDC_ARROW); // Курсор

wcl.lpszMenuName="Mymenu"; // Главное меню

wcl.cbClsExtra=0; // Без дополнительной информации

wcl.cbWndExtra=0;

wcl.hbrBackground=

(HBRUSH)GetStockObject(WHITE_BRUSH); //Белый фон

if(!RegisterClass(&wcl)) // Регистрируем класс окна

return 0;

hwnd=CreateWindow(szWinName, // Создать окно

"Работа с буфером обмена Clipboard ",

WS_OVERLAPPEDWINDOW, // Стиль окна

CW_USEDEFAULT, // x-координата

CW_USEDEFAULT, // y-координата

CW_USEDEFAULT, // Ширина

CW_USEDEFAULT, // Высота

HWND_DESKTOP, // Нет родител. окна

NULL, // Нет меню

hThisInst,// Дескриптор приложения

NULL); // Нет дополнит. аргументов

ShowWindow (hwnd, nWinMode); // Показать окно

UpdateWindow (hwnd); // и перерисовать

hAccel=LoadAccelerators(hThisInst,"Mymenu");

// Загрузить акселераторы

while(GetMessage(&msg,NULL,0,0))

if(!TranslateAccelerator(hwnd,hAccel,&msg))

{

TranslateMessage(&msg); // Исполь. клавиатуру

DispatchMessage (&msg); // Возврат к Windows

}

return msg.wParam;

}

 

// Следующая функция вызывается операционной

// системой Windows и получает в качестве

// параметров сообщения из очереди сообщений

// данного приложения

LRESULT CALLBACK WindowFunc(HWND hwnd,

UINT message,

WPARAM wParam,

LPARAM lParam)

{

int i;

char *p;

char str[255];

switch(message)

{

case WM_COMMAND:

switch(LOWORD(wParam))

{

case ID_OUTTOCLIP:

hGout=GlobalAlloc(GHND|GMEM_DDESHARE,

(DWORD)Maxsize);

p=(char*)GlobalLock(hGout);

strcpy(p,text); // Копирование текста

// в глобальную память

GlobalUnlock (hGout);

if(OpenClipboard(hwnd))

{

EmptyClipboard();

SetClipboardData(CF_TEXT,hGout);

CloseClipboard();

MessageBox(hwnd, text,

"Записано в буфер обмена",

MB_OK);

}

break;

case ID_READFROMCLIP:

if(OpenClipboard(hwnd))

{

hGin=GetClipboardData(CF_TEXT);

p=(char*)GlobalLock(hGin);

// Начинаем копировать текст

// из глобальной памяти */

for(i=0; i<Maxsize; i++)

str[i]= *p++;

str[i]= '\0'; // конец строки

// Закончили копировать текст

GlobalUnlock(hGin);

CloseClipboard();

MessageBox(hwnd, text,

"Прочитано из буфера обмена",

MB_OK);

}

}

break;

case WM_DESTROY: // Завершение программы

PostQuitMessage(0);

break;

default:

// Все сообщения, не обрабатываемые в

// данной функции, направляются на обработку

// по умолчанию

return DefWindowProc(hwnd,message,

wParam,lParam);

}

return 0;

}

 

Для этой программы необходим следующий файл ресурсов Clipboard.rc:

 

#include <Windows.h>

#include "Clip.h"

MYMENU MENU

{

POPUP "Данные"

{

MENUITEM "Записать в буфер", ID_OUTTOCLIP

MENUITEM "Прочесть из буфера",ID_READFROMCLIP

}

}

MYMENU ACCELERATORS

{

VK_F1, ID_OUTTOCLIP, VIRTKEY

VK_F2, ID_READFROMCLIP, VIRTKEY

}

 

Кроме того, потребуется файл определений Clip.h:

 

#define ID_OUTTOCLIP 101

#define ID_READFROMCLIP 102

 

 
 


Работу этой программы иллюстрирует рис. 13.3.

Рис. 13.3. Пример работы с буфером обмена Clipboard

Литература

 

1. Емельянов А.А., Власова Е.А., Денисов Д.В., Емельянова Н.З. Основы программирования для информатиков и инженеров. Часть 1: Алгоритмизация и программирование на языке «С». – М.: ММИЭИФП, 2004. – 208 с.

2. Керниган Б., Ритчи Д. Язык программирования Си. – М.: Финансы и статистика, 2001. – 352 с.

3. Круглински Д. Дж., Уингоу С., Шеферд Дж. Программирование на Microsoft Visual С++ 6.0 для профессионалов. – СПб.: Питер; М.: Русская редакция, 2001. – 864 с.

4. Крупник А.Б. Изучаем Си. – СПб.: Питер, 2002. – 256 с.

5. Крупник А.Б. Изучаем С++. – СПб.: Питер, 2002. – 251 с.

6. Ламот А. Программирование игр для Windows: советы профессионала. – М.: Издательский дом «Вильямс», 2004. – 880 с.

7. Шилдт Г. Программирование на С и С++ для Windows. – К.: Торгово-издательское бюро BHV, 2001. – 408 с.

 


* Селекторные кнопки иногда называют «радиокнопками» (Прим. ред.)

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

 



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2017-03-31 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: