Delphi 3. Библиотека программиста

       

Работа с буфером как с потоком


До своего знакомства с Delphi я пользовался для записи и чтения данных двоичного файла методами BlockWrite и BlockRead. Теперь наступили просвещен ные времена, и я предпочитаю работать с потоками и методами Write и Read. Одна из причин заключается в том, что компоненты Delphi сохраняются в потоках. Следовательно, объект, который умеет сохранять и загружать себя методами TStream.Write и TStream.Read, заметно облегчит процесс программирования.

А вот и другая причина — если объект умеет записываться в поток, он способен перенести себя на любое устройство, представленное в виде потока. Такой объект с одинаковой легкостью записывается как в память (через TMemoryStream), так и на диск.

Создавая поток для нового устройства, вы делаете свой код более гибким и универсальным— и зачастую упрощаете работу с данным устройством. Например, обмен информацией с буфером (clipboard) — занятие на любителя. Конечно, объект Delphi TClipboard вам поможет, но для копирования и вставки нестандартных форматов или больших объемов данных все равно придется вызывать загадочные функции API, имена которых начинаются с Global. Поток из листинга 9.14, напротив, позволяет работать с буфером с помощью знакомых методов Write и Read.

Листинг 9.14. Модуль CLIPSTRM.PAS

unit ClipStrm; interface uses Classes, Clipbrd, Consts, WinProcs, WinTypes; type TClipboardMode = ( cmRead, cmWrite ); TClipboardStream = class( TMemoryStream ) private FMode: TClipboardMode; FFormat: Word; public constructor Create( Format: Word; Mode: TClipboardMode ); destructor Destroy; override; end; implementation constructor TClipboardStream.Create; var Handle: THandle; MemPtr: Pointer; begin inherited Create; FMode := Mode; FFormat := Format; { В "режиме чтения" немедленно читаем данные буфера в поток... } if ( FMode = cmRead ) and Clipboard.HasFormat ( FFormat ) then begin Clipboard.Open; try Handle := Clipboard.GetAsHandle( FFormat ); MemPtr := GlobalLock( Handle ); try Write( MemPtr^, GlobalSize( Handle )); finally GlobalUnlock( Handle ); end; Position := 0; finally Clipboard.Close; end; end; end; destructor TClipboardStream.Destroy; var P: PChar; begin { В "режиме записи" копируем в буфер все содержимое потока... } if FMode = cmWrite then begin P := GlobalAllocPtr( HeapAllocFlags, Size ); try Position := 0; Read( P^, Size ); Clipboard.SetAsHandle( FFormat, GlobalHandle( P )); except GlobalFreePtr( P ); end; end; inherited Destroy; end; end.

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

В результате получается, что объект может с помощью одного и того же кода сохранить себя на диске (TFileStream), в памяти (TMemoryStream) или в буфере; код для его последующей загрузки из разных источников тоже будет одинаковым.



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