Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.01;
Скачать: CL | DM;

Вниз

Сохранение компонентов в файл и чтение из него   Найти похожие ветки 

 
DmitryNekl   (2004-07-19 18:07) [0]

Добрый день. Не знаю, может, мне в БД надо... В общем, вопрос такой:

Создаю форму:
procedure TForm1.FormCreate(Sender: TObject);
begin
 ADOConnection1:=TADOConnection.Create(self);
 ADOConnection1.Name:="ADOConnection1";
 ADOConnection1.LoginPrompt:=False;
 ADOConnection1.ConnectionString:="...";
 ADOConnection1.GetTableNames(Combobox1.Items, False);

 ADOQuery1:=TADOQuery.Create(self);
 ADOQuery1.Connection:=ADOConnection1;

 DataSource1:=TDataSource.Create(self);
 DataSource1.Name:="DataSource1";
 DataSource1.DataSet:=ADOQuery1;

 DBGrid1:=TDBGrid.Create(Form1);
 DBGrid1.Name:="DBGrid1";
 DBGrid1.Parent:=Form1;
 DBGrid1.DataSource:=DataSource1;
end;


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

procedure TForm1.Button6Click(Sender: TObject); // сохраняем табличку в файл
begin
 ADOConnection1.Name:="";
 WriteComponentResFile("ADOConnection1.dfm", ADOConnection1);
 ADOConnection1.Name:="ADOConnection1";

 ADOQuery1.Name:="";
 WriteComponentResFile("ADOQuery1.dfm", ADOQuery1);
 ADOQuery1.Name:="ADOQuery1";

 DataSource1.Name:="";
 WriteComponentResFile("DataSource1", DataSource1);
 DataSource1.Name:="DataSource1";

 DBGrid1.Name:="";
 WriteComponentResFile("DBGrid1.dfm", DBGrid1);
 DBGrid1.Name:="DBGrid1";
end;


А потом пытаюсь прочесть из файла (в другую форму, чистую):
procedure TForm1.Button7Click(Sender: TObject);
var F: TForm;
begin
 F:=TForm4.Create(Form1);
end;


constructor TForm4.Create(AOwner: TComponent); // override;
var
 fname: String;
begin
   RegisterClasses([TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
   CreateNew(AOwner);
   ReadComponentResFile("ADOConnection1.dfm", Self);
   ReadComponentResFile("ADOQuery1.dfm", Self);
   ReadComponentResFile("ADODataSource1.dfm", Self);
   ReadComponentResFile("DBGrid1.dfm", Self);
   Self.Name:="";
   Self.Caption:="...";
   Self.Show;
end;


и получаю ошибку "Property Connected does not exist"...

Как бороться? Заранее спасибо!


 
Defunct ©   (2004-07-20 03:29) [1]

Что-то я вопрос не понял...

что надо сохранить?


 
DmitryNekl   (2004-07-20 09:09) [2]

Исходно задача такая. Пишу приложение для работы с БД. Хочу сделать максимально гибко настраиваемым.

В частности, можно сделать так: настроить все поля в редакторе полей, визуально сформировать соответствующий грид (чтобы названия колонок по-русски отображались и т.д.). Но тогда мы жестко привязываемся к структуре таблиц базы.

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

Вот, собственно, и пытаюсь сначала сохранить, а потом - восстановить...


 
Sun bittern ©   (2004-07-20 09:09) [3]

WriteComponent не сохраняет указатели на внешние компоненты.


 
DmitryNekl   (2004-07-20 09:17) [4]

А как это можно реализовать?


 
Sun bittern ©   (2004-07-20 09:23) [5]

А, ветку на пенсию уже отправели. Ищи сайт TDElphi (адрес непомню) и на этом сайте ищи компоненты LMDTools (там говорят дезайнер есть, но еще не смотрел, можещь тпм реализацию глянуть). Ну или этот же пакет ищи гденибудь в другом месте.


 
DmitryNekl   (2004-07-20 10:28) [6]

В общем, научился я сохранять и загружать:

Сохранение:
 f := TFileStream.Create("c:\stream.vcl", fmCreate);
 f.WriteComponent(DBGrid1);  
 f.Free;

Загрузка:
   f := TFileStream.Create("c:\stream.vcl", fmOpenRead);
   f.ReadComponent(DBGrid1);
   f.Free;

Все работает, но интересный глюк (или я чего не понимаю):

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

С чем это может быть связано и как, собственно, бороться?


 
Sun bittern ©   (2004-07-20 11:08) [7]

>> f.ReadComponent(DBGrid1);

Form2 := TForm(f.ReadComponent(DBGrid1));
Может так?


 
DmitryNekl   (2004-07-20 11:16) [8]

А почему так? Я код не полностью привел, на самом деле в конструкторе второй формы делаю так:
   RegisterClasses([TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
   CreateNew(AOwner);
   f:=TFileStream.Create("c:\stream.vcl", fmOpenRead);
   f.ReadComponent(DBGrid1);
   f.Free;
   DBGrid1.Align:=alClient;
   DBGrid1.Parent:=Self;
   DBGrid1.Visible:=True;

У меня вопрос, в общем-то - почему исчезает грид с первой формы???


 
Sun bittern ©   (2004-07-20 11:37) [9]

var
   FS: TFileStream;
   A: TComponent;
begin
 FS := TFileStream.Create("Nova.dfa", fmOpenRead or fmShareDenyRead);
 try
   A := FS.ReadComponent(nil);
   if A is TControl then
     TControl(A).Parent := Form2;
 finally
   FS.Free;
 end;
end;


 
DmitryNekl   (2004-07-20 11:53) [10]

Спасибо, все заработало! :)
Хотя я и не понимаю, почему :).

Можно ссылочку на какую-нить статью на эту тему?


 
Sun bittern ©   (2004-07-20 12:14) [11]

>> Хотя я и не понимаю, почему :).

FS.ReadComponent(nil);

А гдето в инете давно данный пример откопал. Возможно на королевстве дельфи.
Кстати
  DBGrid1.Align:=alClient;
  DBGrid1.Parent:=Self;
  DBGrid1.Visible:=True;

Данные Published свойства (те что видны в инспекторе объектво) сохраняются WriteComponent (кроме, как я описал выше линек на внешние компоненты) и изменять необязательно. В данном случае Parent не Published свойство, вот и портебовалось указать ему родителя.


 
DmitryNekl   (2004-07-20 13:10) [12]

Нашел еще неприятную особенность... в качестве всяких ADOQuery, ADOConnection при загрузке формы используются те, которые находятся на форме, с которой происходит сохранение грида.

Как бы мне вместе с гридом сохранять и компоненты ADOQuery, ADOConnection, DataSource, а при загрузке грида загружать и их и подключать к гриду?


 
Sun bittern ©   (2004-07-20 13:29) [13]

Может тебе не кусками сохранять, а всю форму в поток слхранить? Как этот вариант?


 
DmitryNekl   (2004-07-20 14:07) [14]

Да, это я умею... но тут прикол в том, что редактирую я все это дело в одной форме, а открываю настроенный грид - в другой. А в первой всяких "лишних" наворотов до дури...


 
Sun bittern ©   (2004-07-20 14:10) [15]

Ты свой мини дизайнер создаешь чтоли :)


 
DmitryNekl   (2004-07-20 14:15) [16]

Не совсем... но стало близко к нему :)

Изначально я делал приложение для работы с БД, но структура БД стала меняться слишком часто... в общем, я решил, что это оптимально :). И в принципе, сделал... осталось тока научиться сохранять/загружать...

А по существу есть мысли?


 
Sun bittern ©   (2004-07-20 16:59) [17]

>> А в первой всяких "лишних" наворотов до дури...

1. Дурь можно вынести на отдельную форму - яля панель инструментов
2. Или. Кинуть нужные компоненты на отдельный TWinControl (например TPanel). Тоесть точто нужно сохранить просаем на эту панельку. Но чтобы вместе с этой панелькой сохранились и компоненты наней, лежащие на ней компоненты должны пренадлежать ей т.е. она должна являться хозяином для них (Owner). Далее сохранить панель в файл (указать только панель, раз для компонентов хозяином является панель, то то что на ней автоматически сохранится в файл)
3. Ну можно еще чего насоченять ;)


 
DmitryNekl   (2004-07-20 18:04) [18]

О, классная мысль (про панельку)! :)
Непременно попробую, спасибо огромное! :)


 
DmitryNekl   (2004-07-21 10:17) [19]

Хрень какая-то... Не работает. Т.е.:

procedure TForm1.FormCreate(Sender: TObject);
begin
 Panel1:=TPanel.Create(Form1);
 Panel1.Parent:=Form1;

 ADOConnection1:=TADOConnection.Create(Panel1);
 ADOConnection1.Name:="ADOConnection1";
 ADOConnection1.LoginPrompt:=False;
 ADOConnection1.ConnectionString:="...";

 ...

 ADOQuery1:=TADOQuery.Create(Panel1);
 ADOQuery1.Connection:=ADOConnection1;

 DataSource1:=TDataSource.Create(Panel1);
 DataSource1.Name:="DataSource1";
 DataSource1.DataSet:=ADOQuery1;

 DBGrid1:=TDBGrid.Create(Panel1);
 DBGrid1.Name:="DBGrid1";
 DBGrid1.Align:=alClient;
 DBGrid1.DataSource:=DataSource1;
 DBGrid1.Parent:=Panel1;
end;


Потом выбираю таблицу БД, грид загружается данными... Сохраняю:

procedure TForm1.Button6Click(Sender: TObject);
var f: TFileStream;
begin
 f := TFileStream.Create("c:\stream1.vcl", fmCreate);
 f.WriteComponent(Panel1);
 f.Free;
end;


Потом читаю в другой форме:

constructor TForm4.Create(AOwner: TComponent);
var
 fname: String;
 FS: TFileStream;
 a1, a2, a3, a4: TComponent;
begin
 RegisterClasses([TPanel, TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
 CreateNew(AOwner);
 FS := TFileStream.Create("c:\stream1.vcl", fmOpenRead or fmShareDenyRead);
 try
   A4 := FS.ReadComponent(nil);
   if A4 is TControl then
   begin
     TControl(A4).Parent := Self;
     TControl(A4).Align :=alClient;
   end;
 finally
   FS.Free;
 end;
end;


Форма появляется, на ней - панелька, на панельке - грид, но грид к таблице не подключен, а пустой :(

Почему? Что делать?


 
Sun bittern ©   (2004-07-21 10:59) [20]

Я же тебе писал WriteComponent не сохраняет указатели на внешние компоненты и методы (события). Ковыряйся в компонентах с исходниками может там нароешь.
Sun bittern ©   (20.07.04 09:23) [5]
Я начинал делать парсер строк для определения ссылки на компоненты и методы используя RTTI но до конца пока не доделал.

Сайт http://www.tdelphi.spb.ru/ раздел компоненты


 
DmitryNekl   (2004-07-21 11:13) [21]

Что-то я не пойму. Я сохраняю панель, которая является owner-ом для:
1. DBGrid
2. ADOConnection
3. ADOQuery
4. DataSource
Вместе с панелью сохраняется грид... почему же не сохраняется все остальное? Где тут внешние компоненты?


 
Sun bittern ©   (2004-07-21 11:33) [22]

TDBGrid.DataSourece := MyDataSource

Вот MyDataSource и не сохранится в свойстве DataSourece компонента TDBGrid. Также как к примеру и TPopupMenu в свойстве PopupMenu компонента TPanel.


 
Sun bittern ©   (2004-07-21 11:52) [23]

Точнее наверно будет сказать так:

В свойстве DataSourece компонента TDBGrid не сохранится указатель на компонент MyDataSource.


 
DmitryNekl   (2004-07-21 12:00) [24]

А еще интересный вопрос. После выхода из конструктора как мне до мой панельки или до грида добраться? Self.ComponentCount выдает 0 (последним оператором в конструкторе)...


 
DmitryNekl   (2004-07-21 12:03) [25]

Sun bittern ©   (21.07.04 11:52) [23]
Точнее наверно будет сказать так:
В свойстве DataSourece компонента TDBGrid не сохранится указатель на компонент MyDataSource.

Я правильно понимаю, что все 4 компонента вместе с панелью сохранились, и достаточно настроить их взаимные связи? Тока вот добраться бы до них :)


 
Sun bittern ©   (2004-07-21 12:10) [26]

Self это форма? Если для компонент Owner панелька, то это действительно должно быть так.


 
Sun bittern ©   (2004-07-21 12:15) [27]

>> 4 компонента вместе с панелью сохранились

Если Owner у них панелька, то должны вместе сней в файл слиться.


 
DmitryNekl   (2004-07-21 12:16) [28]

Да, в конструкторе формы Self - это форма. Для компонент Owner - действительно панелька. НО! КАК МНЕ ДОБРАТЬСЯ ДО КОМПОНЕНТОВ, чтобы настроить их свойства?


 
Sun bittern ©   (2004-07-21 12:24) [29]

Дык. Чей Owner у компонент, у того вроде и надо спрашивать. А у кого? Можешь узнать например так, псоле загрузки: DataSource1.Owner.Name


 
DmitryNekl   (2004-07-21 14:17) [30]

Ничего не понимаю... в конструктор добавил:


(Panel1.Components[1] as TADOQuery).Connection:=(Panel1.Components[0] as TADOConnection);
(Panel1.Components[2] as TDataSource).DataSet:=(Panel1.Components[1] as TADOQuery);
(Panel1.Components[3] as TDBGrid).DataSource:=(Panel1.Components[2] as TDataSource);


Все работает (сообщений об ошибках нет), но грид выводится пустой...


 
Sun bittern ©   (2004-07-21 15:13) [31]

>> Panel1.Components[2] as TDataSource

От куда такая уверенность? Индексы могут ведь и поменяться со временем.

P.S. Можешь свой проект на мыло мне кинуть. Только без *.dcu, *.exe, *.~* и другого мусора.


 
DmitryNekl   (2004-07-21 15:27) [32]

С одной стороны, могу, а с другой - это бесполезно, ибо к базе я подключаюсь в инете (MySQL), и тебе придется настроить источники данных и т.д.

Уверенность - я проверил один раз... если бы что-то изменилось, была бы ошибка приведения типов, а ее не происходит.


 
Sun bittern ©   (2004-07-21 15:36) [33]

DmitryNekl   (21.07.04 15:27) [32]

Может компонентам адошным и таблицам надо в проперти Active в True принудительно указать?


 
Sun bittern ©   (2004-07-21 15:41) [34]

DmitryNekl   (21.07.04 15:27) [32]

после загрузки проверь открыты ли у тебя источники данных (Active = True)


 
DmitryNekl   (2004-07-21 15:45) [35]

Пробовал... однако торможу.
Смотри, фигня какая. Привожу еще раз код:

Создание компонентов на первой форме:

procedure TForm1.FormCreate(Sender: TObject);
begin
 Panel1:=TPanel.Create(Form1);
 Panel1.Name:="Panel1";
 Panel1.Left:=20;
 Panel1.Width:=Form1.Width-40;
 Panel1.Top:=320;
 Panel1.Height:=Form1.Height div 4;
 Panel1.Parent:=Form1;

 ADOConnection1:=TADOConnection.Create(Panel1);
 ADOConnection1.Name:="ADOConnection1";
 ADOConnection1.LoginPrompt:=False;
 ADOConnection1.ConnectionString:="...";

 ADOQuery1:=TADOQuery.Create(Panel1);
 ADOQuery1.Connection:=ADOConnection1;

 DataSource1:=TDataSource.Create(Panel1);
 DataSource1.Name:="DataSource1";
 DataSource1.DataSet:=ADOQuery1;

 DBGrid1:=TDBGrid.Create(Panel1);
 DBGrid1.Name:="DBGrid1";
 DBGrid1.Align:=alClient;
 DBGrid1.DataSource:=DataSource1;
 DBGrid1.Parent:=Panel1;
end;


Код создания второй формы:

constructor TForm4.Create(AOwner: TComponent); // override;
var
 i: integer;
 fname: String;
 FS: TFileStream;
 a4: TComponent;
begin
 RegisterClasses([TPanel, TADOQuery, TADOConnection, TDBGrid, TDataSource, TForm4, TButton]);
 CreateNew(AOwner);
 FS := TFileStream.Create("c:\stream1.vcl", fmOpenRead or fmShareDenyRead);
 try
   A4 := FS.ReadComponent(nil);
   if A4 is TControl then
   begin
     TControl(A4).Parent:=Self;
     TControl(A4).Align:=alClient;
   end;
 finally
   FS.Free;
 end;

 ShowMessage(Panel1.Parent.ClassName);

 (Panel1.Components[1] as TADOQuery).Connection:=(Panel1.Components[0] as TADOConnection);
 (Panel1.Components[2] as TDataSource).DataSet:=(Panel1.Components[1] as TADOQuery);
 (Panel1.Components[3] as TDBGrid).DataSource:=(Panel1.Components[2] as TDataSource);

 Self.Name:="";
 Self.Caption:="Редактирование содержимого таблицы";
 Self.Show;
end;

То, что жирным выделено, до меня дошло вставить туда только что... Выводит Form1, т.е. я играю не с тем объектом.

А оператор
for i:=0 to TControl(A4).ComponentCount-1 do ShowMessage  (TControl(A4).Components[i].ClassName);
вставленный вместо жирного, выводит только TDBGrid... и больше нифига. Это получается, что остальные три объекта не сохраняются вместе с панелькой?


 
Sun bittern ©   (2004-07-21 16:30) [36]

Блин. Выходит, что сохраняются только TControl :^( Щас сам проверил.


 
DmitryNekl   (2004-07-21 16:33) [37]

И что теперь делать? Что ли, сохранять каждый компонент по отдельности и загружать на форму, а потом настраивать связи?


 
Sun bittern ©   (2004-07-21 16:49) [38]

Не знаю поможет ли
http://delphimaster.net/view/5-1089284149/

Как второй извращщенный вариант :(
Поместить не визуальные компоненты в DataModule (для удобства)
Визуальным компонентам назначить уникальный Tag. Полсле загрузки панельки перебрать на ней контролы и проверять Tag. Например если 1, то ага, значит у тебя есть проперти DataSource и назначить ему соотвествующий DataSource из DataModule.

Но это все изврат и неудобно в дальнейшем расширять функциональность. Лучше скачать пакет компонент Sun bittern ©   (20.07.04 09:23) [5] и посомтреть как это профи сделали. Или создавать парсер строк (по типу *.dfm файла) с помощью RTTI.


 
DmitryNekl   (2004-07-21 17:34) [39]

Извращенный вариант не пройдет: смысл именно в том, чтобы сохранять все изменения в составе и описаниях полей и т.д.

А насчет поможет ли - посмотрим... Боюсь, кода профи я не пойму... не настолько глубоко все знаю. :(

Будем учиться :)



Страницы: 1 вся ветка

Текущий архив: 2004.08.01;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.045 c
3-1089199239
Cranky
2004-07-07 15:20
2004.08.01
оцените код , и оптемезуйте


4-1087542911
alexdbases
2004-06-18 11:15
2004.08.01
Появление нового процесса в системе.


1-1089904797
ko
2004-07-15 19:19
2004.08.01
Помогите с SaveDialog


14-1090037247
banderas
2004-07-17 08:07
2004.08.01
Молю о помощи !!!


10-1025241119
Nikols
2002-06-28 09:11
2004.08.01
Работает только на разных машинах...