Всем привет
Delphi 12 / Windows10
В рамках своего хобби посвящаю свободное время изучению Delphi и на данный момент меня интересует тема сохранения и полного восстановления пользовательского интерфейса.
Честно говоря, я не вижу смысла изучать что-либо дальше, пока не освоюсь в этой теме, ибо любая программа должна иметь опцию сохранения и загрузки проект файлов.
Так вот поискав в интернете, я нашел 3 метода, которые посоветовали использовать специалисты Delphi.
1. Memory Stream
2. ini-файл
3. Fire Monkey Save State
Я выбрал метод Memory Stream, потому что он показался мне простым, полным и понятным.
Сразу скажу, что в итоге мне удалось записать и восстановить Форму в/из *.txt-файла с помощью Stream.WriteComponent(Self).
Но в процессе изучения этой темы я столкнулся с двумя проблемами, решение которых я не могу найти.
Проблема 1. (см. рис.)
Когда я сохраняю всю форму через Stream.WriteComponent(Self) в файл *.txt, все события, назначенные компонентам, корректно записываются в файл и восстанавливаются из файла с помощью Stream.ReadComponent(Self). Но если я передаю только Main_Panel через Stream.WriteComponent(Main_Panel), то по какой-то причине все события, назначенные компонентам, не записываются в файл и в результате восстановление из файла оказывается неполным.
Пожалуйста, объясните мне, почему Stream.WriteComponent() ведет себя так странно? Или я что-то делаю не так?
Проблема 2
В результате из-за проблемы 1 я вынужден сохранять всю форму, чтобы восстановление было полным без потери назначенных событий, но после загрузки форма как будто зависает, то есть ее невозможно переместить, скрыть, открыть или закрыть, пока на форме не сработает какое-либо событие, назначенное дочерним компонентам.
Как вы думаете, почему Форма ведет себя таким образом после загрузки компонентов из файла?
Конечно, Проблема 2 не так критична, так как 98% пользователей после загрузки файла проекта выполняют действия внутри Формы, а не с самой Формой, но меня это все равно раздражает и я очень хочу это исправить.
Моя тестовая программа очень простая. На форме в центре находится «Главная панель», внутри которой находится «Панель 1». Сверху находятся две кнопки, управляющие шириной «Панели 1».
Снизу находятся кнопки «Сохранить поток», «Загрузить поток», «Добавить кнопку на Панель 1», «Удалить кнопку с Панели 1». (см. рис.)
Вот часть кода отвечающая за сохранение и восстановления Формы.
////////////////////////////////////////////////////////////////////////////////
procedure TMain_Form.FormCreate(Sender: TObject);
begin
AppPath:= ExtractFilePath(GetCurrentDir());
AppDatFile:= TPath.Combine(AppPath, 'formdata.txt');
end;
////////////////////////////////////////////////////////////////////////////////
procedure TMain_Form.SaveButtonClick(Sender: TObject);
var
FileStream : TFileStream;
MemStream : TMemoryStream;
begin
MemStream := nil;
FileStream := TFileStream.Create(AppDatFile, fmCreate);
try
MemStream := TMemoryStream.Create;
MemStream.WriteComponent(Self); // Main_Panel
MemStream.Position := 0;
ObjectBinaryToText(MemStream, FileStream);
finally
MemStream.Free;
FileStream.Free;
end;
end;
////////////////////////////////////////////////////////////////////////////////
procedure TMain_Form.LoadButtonClick(Sender: TObject);
var
i : Integer;
FileStream : TFileStream;
MemStream : TMemoryStream;
begin
MemStream := nil;
if FileExists(AppDatFile) then
begin
for i := pred(Self.ChildrenCount) downto 0 do
Self.Children[i].Free;
FileStream := TFileStream.Create(AppDatFile, fmOpenRead);
try
MemStream := TMemoryStream.Create;
ObjectTextToBinary(FileStream, MemStream);
MemStream.Position := 0;
MemStream.ReadComponent(Self);
finally
MemStream.Free;
FileStream.Free;
end;
end;
Self.Name:= 'Main_Form';
end;
Вопрос
LBox
Всем привет
Delphi 12 / Windows10
В рамках своего хобби посвящаю свободное время изучению Delphi и на данный момент меня интересует тема сохранения и полного восстановления пользовательского интерфейса.
Честно говоря, я не вижу смысла изучать что-либо дальше, пока не освоюсь в этой теме, ибо любая программа должна иметь опцию сохранения и загрузки проект файлов.
Так вот поискав в интернете, я нашел 3 метода, которые посоветовали использовать специалисты Delphi.
1. Memory Stream
2. ini-файл
3. Fire Monkey Save State
Я выбрал метод Memory Stream, потому что он показался мне простым, полным и понятным.
Сразу скажу, что в итоге мне удалось записать и восстановить Форму в/из *.txt-файла с помощью Stream.WriteComponent(Self).
Но в процессе изучения этой темы я столкнулся с двумя проблемами, решение которых я не могу найти.
Проблема 1. (см. рис.)
Когда я сохраняю всю форму через Stream.WriteComponent(Self) в файл *.txt, все события, назначенные компонентам, корректно записываются в файл и восстанавливаются из файла с помощью Stream.ReadComponent(Self). Но если я передаю только Main_Panel через Stream.WriteComponent(Main_Panel), то по какой-то причине все события, назначенные компонентам, не записываются в файл и в результате восстановление из файла оказывается неполным.
Пожалуйста, объясните мне, почему Stream.WriteComponent() ведет себя так странно? Или я что-то делаю не так?
Проблема 2
В результате из-за проблемы 1 я вынужден сохранять всю форму, чтобы восстановление было полным без потери назначенных событий, но после загрузки форма как будто зависает, то есть ее невозможно переместить, скрыть, открыть или закрыть, пока на форме не сработает какое-либо событие, назначенное дочерним компонентам.
Как вы думаете, почему Форма ведет себя таким образом после загрузки компонентов из файла?
Конечно, Проблема 2 не так критична, так как 98% пользователей после загрузки файла проекта выполняют действия внутри Формы, а не с самой Формой, но меня это все равно раздражает и я очень хочу это исправить.
Моя тестовая программа очень простая. На форме в центре находится «Главная панель», внутри которой находится «Панель 1». Сверху находятся две кнопки, управляющие шириной «Панели 1».
Снизу находятся кнопки «Сохранить поток», «Загрузить поток», «Добавить кнопку на Панель 1», «Удалить кнопку с Панели 1». (см. рис.)
Вот часть кода отвечающая за сохранение и восстановления Формы.
//////////////////////////////////////////////////////////////////////////////// procedure TMain_Form.FormCreate(Sender: TObject); begin AppPath:= ExtractFilePath(GetCurrentDir()); AppDatFile:= TPath.Combine(AppPath, 'formdata.txt'); end; //////////////////////////////////////////////////////////////////////////////// procedure TMain_Form.SaveButtonClick(Sender: TObject); var FileStream : TFileStream; MemStream : TMemoryStream; begin MemStream := nil; FileStream := TFileStream.Create(AppDatFile, fmCreate); try MemStream := TMemoryStream.Create; MemStream.WriteComponent(Self); // Main_Panel MemStream.Position := 0; ObjectBinaryToText(MemStream, FileStream); finally MemStream.Free; FileStream.Free; end; end; //////////////////////////////////////////////////////////////////////////////// procedure TMain_Form.LoadButtonClick(Sender: TObject); var i : Integer; FileStream : TFileStream; MemStream : TMemoryStream; begin MemStream := nil; if FileExists(AppDatFile) then begin for i := pred(Self.ChildrenCount) downto 0 do Self.Children[i].Free; FileStream := TFileStream.Create(AppDatFile, fmOpenRead); try MemStream := TMemoryStream.Create; ObjectTextToBinary(FileStream, MemStream); MemStream.Position := 0; MemStream.ReadComponent(Self); finally MemStream.Free; FileStream.Free; end; end; Self.Name:= 'Main_Form'; end;
9 ответов на этот вопрос
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.