Delphi World - это проект, являющийся сборником статей и малодокументированных возможностей  по программированию в среде Delphi. Здесь вы найдёте работы по следующим категориям: delphi, delfi, borland, bds, дельфи, делфи, дэльфи, дэлфи, programming, example, программирование, исходные коды, code, исходники, source, sources, сорцы, сорсы, soft, programs, программы, and, how, delphiworld, базы данных, графика, игры, интернет, сети, компоненты, классы, мультимедиа, ос, железо, программа, интерфейс, рабочий стол, синтаксис, технологии, файловая система...
Урок 11 - Работа с потоками

Ведущий раздела KOL и MCK: Анатолий aka XVeL
Автор: Борис Моренко
WEB-сайт: http://kol.mastak.ru

Полную версию библиотеки KOL и MCK можно скачать здесь.

Поговорим про потоки в KOL. Вещь безусловно нужная и поэтому очень приятная :). Потоки позволяют сделать более гибкой работу по обмену и выводу данных из различных источников. Для разных источников (носителей), чтение данных происходит по разному, а потоки унифицируют этот процесс. Теоретическую часть этого вопроса можно найти в любой книжке по Delphi, так что особо разглагольствовать я не буду. Скажу лишь что во многих случаях без них совершенно не обойтись. Например :
Вы в ресурс вашей программы поместили gif или jpg файл (ну не хочется вам таскать их отдельными файлами). Разумеется вы захотите когда-нибудь показать их миру . Но не все так просто. Объекты PGif и PJpeg не читают данные из ресурса (только поток или файл. см предыдущий урок). Т.е. у нас сложилась так, что ресурс (источник), не может передать информацию объектам PGif или PJpeg. Вот тут и приходят на помощь потоки. И таких примеров если покопаться можно отыскать достаточно.

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

Конструкторы.

Для создания потока в памяти (чтение и запись):
function NewMemoryStream: PStream;

Для создания потоков работающих с файлами:

  1. function NewReadFileStream( const FileName: String ): PStream;
  2. function NewWriteFileStream( const FileName: String ): PStream;
  3. function NewReadWriteFileStream( const FileName: String ): PStream;

FileName - имя фала на диске.
Эти три конструктора отличаются по целям для которых вы собираетесь использовать файл.
1-й для чтения ; 2-й для записи ; 3-й для записи и чтения.

Основные свойства PStream

Свойства PStream
Свойство
Описание
Size: DWord; Возвращает размер данных в потоке.
Position: DWord; Текущая позиция в потоке
Memory: Pointer; Указатель. Только для потоков созданных в памяти
Handle: THandle; Хэндл. Только для файловых потоков

Список методов:

Методы PStream
Метод
Описание
function Read( var Buffer; Count: DWord ): DWord; Чтение в буфер (Buffer) Count байт из потока
function Write( var Buffer; Count: DWord ): DWord; Запись Count байт в поток из буфера Buffer начиная с текущей позиции.
function WriteStr( S: String ): DWORD; Запись любой паскалевской строки (не заканчивающейся нулем) в поток. Запись происходит с текущей позиции.

А теперь сам обещанный пример. Для его работы у вас должен быть установлен KolGif (можете скачать в разделе файлы). Вы также должны создать ресурс содержащий любой gif с именем logo.gif (в моем случаем это логотип нашего сайта).
Для этого создайте файл с расширение *.rc (у меня pic.rc) содержащий следующий текст:
LOGOTIP RCDATA "logo.gif"
Скомпилируйте при помощи brcc32.exe:
brcc32.exe pic.rc

В процедуре SavePic выполняется сохранения ресурса на жесткий диск (эта процедура происходит при клике по рисунку). В ShowForma gif рисунок извлекается из ресурса и выводится на экран.
В обоих процедурах используется функция Resource2Stream. Она переводит данные из ресурса в поток.

program Primer11;

uses
  Kol,
  Messages,
  Windows,
  KolGif;

{$R *.RES}
{$R pic.res}
var
  forma,
  pb: pControl;
  Gif: pGif;
  PicStream: PStream;
////////////////////////////////////////////////////////////////////////// 
// рисование избражения 
procedure DrawPaint( Dummy: Pointer; Sender: PControl; DC: HDC );
begin
  Gif.Draw(PB.Canvas.Handle, 0, 0);
end;
////////////////////////////////////////////////////////////////////////// 
//"забрасываем" ресурс на диск 
procedure SavePic( Dummy : Pointer; Sender: PControl );
begin
  //GetWindowsDir[1] - будем мусорить на системном диске :) 
  //создаем файл-поток для изображения 
  PicStream := NewWriteFileStream(GetWindowsDir[1] + ':\logo.gif');
  // переводим данные из ресурса в поток 
  Resource2Stream(PicStream, HInstance, 'LOGOTIP', RT_RCDATA);
  PicStream.free;
end;
////////////////////////////////////////////////////////////////////////// 
// показываем картинку из ресурса 
procedure ShowForma( Dummy : Pointer; Sender: PControl );
begin
  PicStream := NewMemoryStream; //создаем поток для изображения 
  // переводим данные из ресурса в поток 
  Resource2Stream(PicStream, HInstance, 'LOGOTIP', RT_RCDATA);
  //Указываем с какой позиции у нас будут читаться данные 
  PicStream.Position := 0;

  gif := NewGif;
  gif.LoadFromStream(PicStream);

  PB := NewPaintBox(forma);
  PB.OnPaint := TOnPaint( MakeMethod( nil, @DrawPaint ) );
  // в случае клика по картинке сохраняем ее на диск 
  PB.OnClick := TOnEvent( MakeMethod( nil, @SavePic ) );

  PB.Width := gif.Width ;
  PB.Height:= gif.Height;
  PB.CenterOnParent;

  PicStream.free;
end;
////////////////////////////////////////////////////////////////////////// 
begin
  Applet := NewApplet('Работа с потоком');
  Forma := NewForm(Applet, 'Работа с потоком (вывод gif)');
  Forma.SetSize(310, 120);
  Forma.CenterOnParent;
  Forma.Font.FontName := 'MS Sans Serif';
  Forma.Font.FontHeight := 9;
  Forma.onShow :=  TOnEvent(MakeMethod(nil, @ShowForma));
  Run(Applet);
end.

Исходный текст : 1,9 Кб ; размер программы: 56,5Кб (без сжатия и замены System). Из этих 57 килобайт около 12 занимает картинка. Вот что вы должны увидеть :

 Пример не совсем выгоден с точки зрения экономии дискового пространства :) Дело в том что логотип в bmp весит всего 24 Кб (цвет 8 бит), а  KOLGif примерно 12Кб  добавляет в размер программы + 12 Кб рисунок. Но при больших картинках помещать в ресурс gif уже более разумней.

Проект Delphi World © Выпуск 2002 - 2004
Автор проекта: ___Nikolay