- •Литература
- •Содержание
- •1. Основные понятия ооп
- •2. Программирование для Windows
- •3. Визуальное программирование и среда Delphi
- •Создание приложений в средеDelphi
- •Компоненты общего назначения tMainMenu- главное меню формы (программы)
- •TPopupMenu- вспомогательное (локальное) меню
- •TLabel- метка для отображения текста
- •TEdit-ввод и отображение строки
- •TMemo- ввод и отображение текста
- •TButton- кнопка
- •TBitBtn- кнопка с изображением
- •TSpeedButton- кнопка для инструментальных панелей
- •TCheckBox- независимый переключатель
- •TRadioButton- зависимые переключатели
- •TRadioGroup- группа зависимых переключателей
- •TListBox- список выбора
- •TComboBox- раскрывающийся список выбора
- •TPanel- панель
- •TTabControl- набор закладок
- •TPageControl- набор страниц с закладками
- •4. Особенности языка ооп Object Pascal
- •Процедуры и функции Выход из процедур и фукнций и возврат результата
- •Передача параметров
- •Параметры со значениями по умолчанию
- •Перегрузка функций
- •Динамическое распределение памяти
- •Указатели
- •Операции с указателями
- •Операция @
- •Самоадресуемые записи
- •Динамические массивы Одномерные динамические массивы
- •Многомерные динамические массивы
- •Исключения и их обработка
- •Защита кода зачистки в блокахtry...Finally
- •Защита кода зачистки на уровне модуля — разделfinalization
- •Обработка исключений в блокахtry...Except
- •Последовательность обработки исключений
- •5. Классы и объекты
- •Классы и объекты
- •Инкапсуляция
- •Наследование
- •Полиморфизм
- •Составляющие класса Поля
- •Одноименные методы
- •Свойства
- •События
- •Объявление класса
- •Операции с классами
- •Ссылки на классы
- •TObjectи информация о классах
- •Регистрация и обнаружение классов
- •6. Создание объектов во время выполнения, поиск компонентов
- •Клонирование объектов
- •Поиск компонента
- •Двукратное освобождение объекта
- •7. Построение собственных компонентов
- •Как и для чего следует строить компоненты
- •Общие руководящие принципы
- •Ключевые идеи
- •Компиляция компонентов
- •Отладка компонентов
- •Примечание
- •Примечание
- •Примечание
- •8. Работа с потоками
- •Классы потоковDelphi
- •Файловые потоки
- •Примечание
- •Методы потоков в действии: программаMemoStr
- •Потоки памяти
- •Пример программыMemoryS
- •Примечание
- •Написание заказного класса потока
- •9. Работа с com-объектами, использование серверов ole-автоматизации
Потоки памяти
В примере MemoStr показано, как можно копировать файл, используя объект TFileStream. Чтобы это сделать, нет необходимости создавать буфер в оперативной памяти, так как классы TFileStream делают это автоматически.
Однако бывают случаи, когда следует явно создать область памяти так, чтобы выполнить действия над данными без ограничения скорости доступа к файлу. В этом случае создается объект TMemoryStream, работающий точно так же, как любой другой поток (со свойствами размера и позиции), но использующий память вместо данных из файла на диске.
Очевидно, что вам, прежде всего, придется импортировать данные в область памяти. Чтобы сделать это, класс TMemoryStream определяет специальные методы обмена содержимого памяти с другими потоками, которыми могут быть TFileStream, THandleStream или другой объект потока. Объекты TMemoryStream особенно полезны, когда необходимо создать временный поток или моделировать временный файл в памяти.
В дополнение к свойствам size и Position, наследуемым из класса TStream, класс TMemoryStream наследует свойство Memory из класса TCustomMemoryStream. Это свойство просто возвращает указатель на блок памяти, которым манипулирует объект TMemoryStream. Как только получен этот указатель, сразу же можно выполнить необходимые действия; но их нельзя делать непосредственно, потому что данное свойство предназначено только для чтения. Чтобы связать объект с другим блоком памяти (возможно уже содержащим данные), необходимо использовать метод SetPointer.
Пример программыMemoryS
Исследуем, например, программу MemoryS. В этой программе задаются две кнопки: одна — для загрузки данных из файла в TMemoryStream, а другая — для отображения этих данных с использованием свойства Memory, упомянутого выше. Изображение на рис. 3.2 показывает основную форму примера MemoryS.
unit MsFormR;
interface
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdDtls, ExtDrls;
type
Т Form1 =class(TForm) OpenDialogl: TOpenDialog;
Сначала обратите внимание, что поток памяти объявлен, как внутреннее поле формы типа private. Это сделано для того, чтобы использовать тот же объект TMemoryStream для вызова функции или процедуры. Одно из этих обращений — процедура ShowMemStr, используемая для отображения содержимого потока памяти через свойство Memory.
private
MemStrl: TMemoryStream;
procedure ShowMemStr;
Как и следовало ожидать, поток памяти создается в обработчике события формы OnCreate.
procedure TForml.FormCreate(Sender: TObject);
begin
MemStrl:= TMemoryStream.Create;
end;
Точно так же он удаляется в обработчике события формы OnDestroy:
procedure TForml.FormDestroy(Sender: TObject);
begin
MemStrl.Free;
end;
Когда пользователь нажимает кнопку «Load File», данные загружаются в TMemoryStream с использованием TFileStream:
procedure TForml.ButtonlClick(Sender: TObject);
var
Strl: TFileStream;
begin
OpenDialogl.Filter:='Any file (*.*)!*.*';
OpenDialogl.DefaultExt:= '*'; '
if OpenDialogl.Execute then
begin
Strl := TFileStream.Create(OpenDialogl.FileName, fmOpenRead);
try
MemStrl.LoadFromStream(Strl);
ShowMemStr;
Button2.Enabled := true;
finally
Strl.Free;
end;
end;
end;
Единственный новый код, добавленный здесь — это обращение к методу LoadFromStream, который просто копирует данные из потока файла в поток памяти. Так как класс TMemoryStream предоставляет метод LoadFromFile, его можно использовать следующим образом.
procedure TForml.ButtonlClick(Sender: TObject);
begin
OpenDialogl.Filter:='Any file (*.*)!*.*';
OpenDialogl.DefaultExt :='*';
if OpenDialogl.Execute then begin
MemStrl.LoadFromFile(OpenDialogl.FileName);
ShowMemStr;
end;
end;
Затем данные просто копируются из потока памяти в компонент Memo, используя метод LoadFromStream класса ТМето.
Поток памяти в Memo копируется прямолинейно:
procedure TForml.ShowMemStr;
begin
Memol.Lines.LoadFromStream(MemStrl);
end;
Очевидно, что можно просто загрузить файл непосредственно в компонент Memo, заменив обработчик события загрузки файла Load File на следующий код:
procedure TForml.ButtonlClick(Sender: TObject);
begin
OpenDialogl. Filter : = 'Any file (*,*)!*.*'•;
OpenDialogl.DefaultExt:= ' * ' ;
if OpenDialogl.Execute then
begin
Memol.Lines.LoadFromFile(OpenDialogl.FileName);
end;
end;
Однако этот подход не инициализировал бы поток памяти данными, как будет сделано в следующем примере.
В заключение добавим кнопку «Show Data». Когда пользователь нажмет эту кнопку, выполнится довольно сложный код для отображения данных в потоке памяти через свойство Memory. В первой версии примера (отсутствует на компакт-диске) использовался следующий код:
procedure TForml.Button2Click(Sender: Tobject);
var
pch: PChar;
begin
pch := MemStrl.Memory;
while (pch <> nil) and (MessageDlg('Character is ' + pch^ + #13#13 + 'Do you want to see the following one?', mtConfirmation, [mbYes, mbNo], 0) = mrYes) do
Inc(pch);
end;
Эта функция начинается инициализацией указателя типа Char с именем pch, чтобы адресовать размещение памяти в начале потока памяти. Затем записан цикл while, проверяющий сначала, имеет ли указатель pch значение nil, а затем отображающий окно диалога и проверяющий ответ пользователя. При отображении окна диалога формируется строка, содержащая символ, адресуемый указателем типа Char, простым изменением указателя (pch^). Если пользователь выбирает кнопку «Yes» в этом диалоговом окне, мы увеличиваем указатель, используя Inc(pch).
Для анализа каждого последовательного символа просто увеличивается указатель. Обратите внимание, что процедура Inc использована вместо оператора:
pch := pch + 1;
Хотя Object Pascal поддерживает арифметические операции над указателями для некоторых типов данных (типа PChar), это сделано потому, что они не поддерживаются как общая возможность языка. Объявление
var
pch: ^Char;
сделало бы невозможным применение стандартных арифметических действий над указателем.
Напротив, процедура Inc управляет указателями, основанными на размере адресуемых данных. Так как тип указателя определяет, что он адресует отдельные байты (символы), вызов Inc с этим типом указателя просто переместит указатель для адресации следующего байта.