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

Загвоздка: компоненты со свойствами-компонентами


Единственное ограничение этих методов заключается в том, что некоторые типы компонентов нельзя сохранить напрямую. Речь идет о компонентах, которые содержат другие компоненты в качестве свойств.

Проблема возникает при попытке загрузить такие компоненты-свойства из файла. Поскольку эти компоненты сохраняются как самостоятельные объекты, попытка загрузить их как свойства другого компонента приводит к возникновению исключения и выдаче сообщения «A component named Widget1 already exists» («Компонент с именем Widget1 уже существует»).

К счастью, эта проблема присуща всего четырем типам компонентов: TMainMenu, TMenuItem, TPopupMenu и TForm.

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

В листинге 12.9 приведен код сохранения свойств формы, выполняемый при обработке события FormCloseQuery. Важнейшие фрагменты этого кода подробно рассматриваются ниже.

Листинг12.9. Обработчик события FormCloseQuery

procedure TFrmMain.FormCloseQuery(Sender: TObject; var CanClose: Boolean); var Writer : TWriter; FileStream : TFileStream; i : Integer; TempRect : TRect; begin { Расширение файла .HPD == High Performance Delphi } { На всякий случай удалим старый файл с расширением HPD. } DeleteFile(ExtractFilePath (Application.ExeName) + TObject(Self).ClassName + '.HPD'); { Теперь можно записывать его заново: } FileStream := TFileStream.Create(ExtractFilePath (Application.ExeName) +TObject(Self).ClassName + '.HPD',fmOpenWrite or fmCreate); for i := 0 to ComponentCount-1 do begin { Некоторые элементы нежелательно (и даже невозможно) сохранить таким способом. К счастью, нам и не придется их сохранять... } if ((Components[i] is TSizingRect) or (Components[i] is TMenu) or (Components[i] is TMenuItem) or (Components[i] is TPopupMenu) or (not(Components[i] is TControl))) then Continue; Writer := TWriter.Create(FileStream, SizeOf(Components[i])); Writer.WriteRootComponent(Components[i]); Writer.Free; end; { Сохранение свойств формы } TempRect.Top := Self.Top; TempRect.Left := Self.Left; TempRect.Bottom := TempRect.Top + Self.Height; TempRect.Right := TempRect.Left + Self.Width; FileStream.Write(TempRect, SizeOf(TRect)); FileStream.Write(Self.Color, SizeOf(TColor)); FileStream.Free; { Не забудьте разрешить закрытие формы! } CanClose := True; end;

Давайте подробно рассмотрим этот метод. Прежде всего мы для надежно сти удаляем старый файл *.HPD, а затем создаем его заново:

FileStream := TFileStream.Create(ExtractFilePath (Application.ExeName) + TObject(Self).ClassName + '.HPD',fmOpenWrite or fmCreate);

Затем мы отыскиваем те элементы, которые невозможно сохранить, и не пытаемся ничего с ними делать:

for i := 0 to ComponentCount-1 do begin { Некоторые элементы нежелательно (и даже невозможно) сохранить таким способом. К счастью, нам и не придется их сохранять... } if ((Components[i] is TSizingRect) or (Components[i] is TMenu) or (Components[i] is TMenuItem) or (Components[i] is TPopupMenu) or (not(Components[i] is TControl))) then Continue;

Если компонент можно сохранить, мы записываем его в поток:

Writer := TWriter.Create(FileStream, SizeOf(Components[i])); Writer.WriteRootComponent(Components[i]); Writer.Free;

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

TempRect.Top := Self.Top; TempRect.Left := Self.Left; TempRect.Bottom := TempRect.Top + Self.Height; TempRect.Right := TempRect.Left + Self.Width; FileStream.Write(TempRect, SizeOf(TRect)); FileStream.Write(Self.Color, SizeOf(TColor)); FileStream.Free;

Наконец, мы устанавливаем флаг, разрешающий закрытие формы:

CanClose := True;



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