Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Теоретические сведения. Функция GlobalAlloc выделяет из кучи указанное число байт



GlobalAlloc

Функция GlobalAlloc выделяет из кучи указанное число байт. В Win32 менеджер памяти не выполняет различия между локальной и глобальной кучей.

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

function GlobalAlloc(

uFlags: UINT; // атрибуты выделения

dwBytes: DWORD // количество выделяемых байт

): HGLOBAL; stdcall;

Параметры

uFlags [in]
Указывает каким образом производить выделение памяти. Если в качестве параметра указан нуль, то по умолчанию используется значение GMEM_FIXED. Указанный параметр может быть комбинацией указанных ниже значений, недопустимые комбинации специально оговорены:

Флаг Назначение
GHND Комбинация флагов GMEM_MOVEABLE и GMEM_ZEROINIT.
GMEM_FIXED Выделяет фиксированную память. Возвращаемое значение указатель.
GMEM_MOVEABLE Выделяет перемещаемую память. В Win32 блоки памяти никогда не могут перемещаться в физической памяти, но они могут быть перемещены внутри владеющими ними кучи. Возвращаемое значение является дескриптором объекта в памяти. Для того, что получить указатель на память, следует воспользоваться функцией GlobalLock. Указанное значение нельзя комбинировать с флагом GMEM_FIXED.  
GMEM_ZEROINIT Инициализирует память нулями.
GPTR Комбинация флагов GMEM_FIXED и GMEM_ZEROINIT.

Функции для работы с Clipboard

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

Перед тем как выполнить запись или чтение данных, приложение должно получить доступ к Clipboard, открыв ее при помощи функции OpenClipboard:

BOOL WINAPI OpenClipboard(HWND hwnd);

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

Если доступ к Clipboard получен, функция OpenClipboard вернет значение TRUE. Если же Clipboard уже открыт другим приложением, эта функция вернет значение FALSE.

После использования приложение должно закрыть Clipboard, вызвав функцию CloseClipboard:

BOOL WINAPI CloseClipboard(void);

Эта функция в случае успеха возвращает значение TRUE, а в случае ошибки - FALSE.

Содержимое открытого Clipboard может быть сброшено функцией EmptyClipboard:

BOOL WINAPI EmptyClipboard(void);

Функция EmptyClipboard возвращает значение TRUE при нормальном завершении или FALSE при ошибке.

Для выполнения записи данных в Clipboard приложение должно использовать функцию SetClipboardData:

HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE hData);

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

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

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

Приведем список предопределенных форматов данных для Clipboard. Соответствующие константы определены в файле windows.h.

Константа Описание формата данных
CF_TEXT Текстовые данные в виде массив символов. Каждая строка завершается комбинацией символов "\r\n", весь массив закрыт двоичным нулем
CF_OEMTEXT Аналогично предыдущему, однако буфер содержит символы в кодировке OEM
CF_BITMAP Битовое изображение в формате, который зависит от устройства отображения (DDB)
CF_METAFILEPICT Метафайл
CF_DIB Битовое изображение в формате, который не зависит от устройства отображения (DIB)
CF_PALETTE Палитра цветов. Используется при записи в Clipboard битовых изображений DIB
CF_SYLK Формат Microsoft Symbolic Link. Этот формат предназначен для передачи текстовых данных, причем каждая строка заканчивается комбинацией символов "\r\n". Используется в некоторых программных продуктах Microsoft
CF_DIF Формат Data Interchange Format. Аналогично формату CF_SYLK, формат CF_DIF предназначен для передачи текстовых данных
CF_TIFF Графическое изображение в формате Tag Image File Format, который был разработан Microsoft, Aldus Corporation и Hewlett-Packard
CF_PENDATA Этот формат данных используется в расширении операционной системы Windows, педназначенном для работы с перьевым вводом
CF_RIFF Формат Resource Interchange File Format. Мы рассказывали о нем в томе "Библиотеки системного программиста", посвященном системам мультимедиа
CF_WAVE Звуковые данные. Подмножество формата Resource Interchange File Format
CF_OWNERDISPLAY Формат данных определяется приложением, записавшим такие данные в Clipboard. Это же приложение отвечает за отображение данных
CF_DSPTEXT Текстовое представление данных, формат которых определен приложением
CF_DSPBITMAP Представление данных, формат которых определен приложением, в виде битового изображения
CF_DSPMETAFILEPICT Представление данных, формат которых определен приложением, в виде метафайла

Для чтения данных из Clipboard используется функция GetClipboardData:

HANDLE WINAPI GetClipboardData(UINT uFormat);

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

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

Запись данных в Clipboard

Для того чтобы записать данные в Clipboard, вы должны выполнить следующую последовательность действий.

Открыть Clipboard функцией OpenClipboard

Сбросить содержимое Clipboard функцией EmptyClipboard

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

Зафиксировать полученный блок памяти функцией GlobalLock

Записать в зафиксированный блок памяти данные

Расфиксировать блок памяти функцией GlobalUnlock

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

Закрыть Clipboard функцией CloseClipboard

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

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

Дело в том, что при записи в Clipboard никакого перемещения данных не происходит. Функция SetClipboardData изменяет атрибуты передаваемого ей блока памяти таким образом, что этот блок памяти изменяет своего "хозяина", переходя в собственность операционной системы Windows и приобретая атрибут GMEM_DDESHARE.

Если приложение заказало глобальный блок памяти без атрибута GMEM_DDESHARE, этот блок памяти принадлежит приложению. Оно отвечает за уничтожение такого блока памяти. Если же приложение "забыло" уничтожить заказанный ей глобальный блок памяти, Windows уничтожает блок памяти сама при завершении приложения.

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

Если приложение снабдит блок памяти атрибутом GMEM_DDESHARE, Windows не будет автоматически уничтожать его при завершении работы приложения. Приложение обязано уничтожить его самостоятельно, как только этот блок памяти перестанет быть нужным.

Из всего сказанного выше следует правило:

Если вы записали данные в Clipboard, отдав идентификатор глобального блока памяти функции SetClipboardData, больше не используйте этот идентификатор для адресации данных

Почему нельзя использовать идентификатор блока памяти, переданный функции SetClipboardData?

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

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

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

Все операции с Clipboard от его открытия и до закрытия должны выполняться в одном обработчике сообщения. Нельзя открывать Clipboard в обработчике одного сообщения, а закрывать в обработчике другого сообщения. Между открытием и закрытием Clipboard нельзя создавать диалоговые панели или выполнять другие действия, которые могут повлечь за собой создание диалоговых панелей (например, вызов функций SendMessage или PeekMessage)

Чтение данных из Clipboard

Рассмотрим теперь процедуру чтения данных из Clipboard. Приложение должно сделать следующее.

Открыть Clipboard функцией OpenClipboard

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

Зафиксировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalLock

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

Расфиксировать блок памяти, идентификатор которого получен от функции GetClipboardData, функцией GlobalUnlock

Закрыть Clipboard функцией CloseClipboard

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

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





Дата публикования: 2015-10-09; Прочитано: 271 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.014 с)...