TDragDropInfo CreateHDrop преобразует информацию


о перетаскиваемых файлах
function TDragDropInfo.CreateHDrop : HGlobal;

var RequiredSize : Integer; i : Integer; hGlobalDropInfo : HGlobal; DropFiles : PDropFiles; c : PChar; begin { Построим структуру TDropFiles в памяти, выделенной через GlobalAlloc. Область памяти сделаем глобальной и совместной, поскольку она, вероятно, будет передаваться другому процессу. } { Определяем необходимый размер структуры } RequiredSize := sizeof (TDropFiles);
for i := 0 to Self.Files.Count-1 do begin { Длина каждой строки, плюс 1 байт для терминатора } RequiredSize := RequiredSize + Length (Self.Files[i]) + 1; end; { 1 байт для завершающего терминатора } inc (RequiredSize);
hGlobalDropInfo := GlobalAlloc ((GMEM_SHARE or GMEM_MOVEABLE or GMEM_ZEROINIT), RequiredSize);
if (hGlobalDropInfo <>
0) then begin { Заблокируем область памяти, чтобы к ней можно было обратиться } DropFiles := GlobalLock (hGlobalDropInfo);
{ Заполним поля структуры DropFiles } { pFiles -- смещение от начала структуры до первого байта массива с именами файлов. } DropFiles.pFiles := sizeof (TDropFiles);
DropFiles.pt := Self.FDropPoint; DropFiles.fNC := Self.InClientArea; DropFiles.fWide := False; { Копируем каждое имя файла в буфер. Буфер начинается со смещения DropFiles + DropFiles.pFiles, то есть после последнего поля структуры. } c := PChar (DropFiles);
c := c + DropFiles.pFiles; for i := 0 to Self.Files.Count-1 do begin StrCopy (c, PChar (Self.Files[i]));
c := c + Length (Self.Files[i]);
end; { Снимаем блокировку } GlobalUnlock (hGlobalDropInfo);
end; Result := hGlobalDropInfo; end;

Данная функция вычисляет требуемый размер данных (он равен размеру записи TDropFiles, определенной в модуле ShlObj, плюс общая длина всех имен файлов), выделяет область памяти и заполняет структуру. Память выделяет ся из глобального пула (global heap) Windows с атрибутом «общая» (GMEM_SHARE), чтобы ее можно было передавать другим приложениям. Обращения к выделенной памяти осуществляются через логический номер типа HGlobal. Имен

но его мы возвращаем вызывающей стороне, которая обязана освободить данные (функцией API GlobalFree) после завершения работы с ними.



Интерфейсы IDropSource и IDataObject реализуются в файле DRAGDROP.PAS (листинг 4.5) объектами TFileDropSource и THDropDataObject соответственно. Объект TFileDropSource выглядит очень просто. Его конструктор просто вызывает конструктор TInterfacedObject, а затем задает начальное значение счетчика ссылок функцией _AddRef. Функция GiveFeedback просто приказывает DoDragDrop использовать стандартные варианты курсора, а QueryContinueDrag проверяет флаг клавиши Escape и состояние кнопок мыши, определяя по ним, следует ли завершить, продолжить или отменить операцию перетаскивания. В общем, ничего необычного.

THDropDataObject выглядит посложнее. Конструктор создает объект TDragDrop Info, который представляет собой пустой список файлов. Затем вызывающая сторона заносит файлы в список методом Add. Деструктор объекта освобожда ет объект TDragDropInfo, если он существует. Из всех методов интерфейса IData Object реализованы только GetData, QueryGetData и EnumFormatEtc. Другие методы возвращают коды, показывающие, что они (методы) не поддерживаются объектом.

QueryGetData просматривает переданную запись TFormatEtc и проверяет, поддерживается ли формат запрашиваемых данных. Если формат поддержи вается, код возврата показывает, что GetData, вероятно, сможет воспроизвес ти данные. EnumFormatEtc создает и возвращает объект IEnumFormatEtc по статическому массиву структур TFormatEtc. Функция GetData проверяет, допустим ли запрашиваемый формат (для чего снова вызывает QueryGetData), убеждается в наличии данных для воспроизведения и затем вызывает TDragDropInfo.Create HDrop. Последний метод создает глобальную область памяти, которая возвращается вызывающей стороне через передаваемую запись TStgMedium. За освобождение данных отвечает вызывающая сторона (то есть клиент перетаски вания).



Содержание раздела