Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2006.09.10;
Скачать: [xml.tar.bz2];

Вниз

Как скопировать компонент в run-time?   Найти похожие ветки 

 
Piter ©   (2006-07-28 17:45) [0]

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

Возникает вопрос - как "множить" панельки? Хотелось бы настроить одну панель, а потом ее просто клонировать, то что делается при CTRL+C / CTRL + V если ткнуть на компоненте в design-time.

Есть более-менее простые пути решения вопроса? Думал о сохранении компонента в поток, но ведь на этом компоненте находятся и другие компоненты, их бы тоже надо "проклонировать" :(

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


 
Мефисто   (2006-07-28 17:53) [1]


> Есть более-менее простые пути решения вопроса? Думал о сохранении
> компонента в поток, но ведь на этом компоненте находятся
> и другие компоненты, их бы тоже надо "проклонировать" :(


Можно и такой вариант рассмотреть. Только при загрузке копии панельки из патока будет AV что компонент с таким именем уже существует. Поэтому, компонентам с которых будет создоваться клон надо .Name := "";


 
Piter ©   (2006-07-28 18:30) [2]

понятно. Но я обозначил проблему - на этом компоненте находятся и другие компоненты.


 
Мефисто   (2006-07-28 18:47) [3]


> на этом компоненте находятся и другие компоненты.


А разве нельзя сохранять компонент с дочерними компонентами на нем?
В этом плане проблем не должно быть.

P.S. или я тебя не верно понимаю?


 
Piter ©   (2006-07-28 18:54) [4]

Мефисто   (28.07.06 18:47) [3]
А разве нельзя сохранять компонент с дочерними компонентами на нем?


вообще то в этом вопрос тоика заключается. Ты решил мой вопрос мне же переадресовать? :)


 
Мефисто   (2006-07-28 19:22) [5]


> Piter ©   (28.07.06 18:54) [4]


Сохранять контрол со всеми компонентами на нем можно. Но нужно учесть Мефисто    (28.07.06 17:53) [1].

Здесь сохраняется TPageControl со всеми TTabShet-ами и тем что лежит на TTabShet. А вот крутится с именами компонентов тебе придется в зависимости как и чего у тебя устроено. Можешь имена компонетов сразу в DesignTime удалить.

Procedure SaveProject(AFileName: TFileName);
 var
   FS: TFileStream;
begin
 FS := TFileStream.Create(AFileName, fmCreate or fmShareDenyRead);
 try
   FS.WriteComponent(Edit_FC.PageProject);
 finally
   FS.Free;
 end;
End;

Procedure LoadProject(AFileName: TFileName);
var
 FS: TFileStream;
 I: Integer;
begin
 FS := TFileStream.Create(AFileName, fmOpenRead or fmShareDenyRead);
 try
   Edit_FC.PageProject := TPageControl(FS.ReadComponent(Edit_FC.PageProject));
 finally
   FS.Free;
 end;
End;


 
Мефисто   (2006-07-28 19:37) [6]


> Мефисто   (28.07.06 19:22) [5]


Да, есть один офигенный минус. Ссылки на события (Events) не копируются. Надо вручную их навешивать. Еще помнится, в сети можно найти опенсорц компоненты которые сохроняют компоненты или форму в файл т.е. сохраняются все published свойства и события. Поищи и посмотри реализацию в них и можешь применить к своему копированию компонентов.

По событиям: теоритически. В клонированном объекте я так думаю индексы: TControl.Components[I]
TControl.Controls[I]
как и у оригинала (ского клонировали).

Т.е. пробежаться по этому массиву и через RTTI проверить есть ли событие на интересующем тебя событии. Если событие не пустое, то навешать его на клон.

uses TypInfo;

GetMethodProp()
SetMethodProp()


 
Piter ©   (2006-07-28 21:23) [7]

Хм... То есть, в потоке сохраняются и все сведения о компонентах, которые принадлежат нужному компоненту?

Странно... Он при считывании из потока создает что ли их всех...


 
Piter ©   (2006-07-28 21:23) [8]

Мефисто   (28.07.06 19:37) [6]
Ссылки на события (Events) не копируются


а вот это странно.


 
Мефисто   (2006-07-28 22:23) [9]

Piter  ©   (28.07.06 21:23) [8]

В поток сохраняются все published свойства. Все что доступно через RTTI. А Events - это указатель на код метода. Т.е. смысл сохранять указатель если при следующем запуске ПО он изменится. Можешь попытаться сделать парсер :) Просмотри форму ввиде ресурса и обрати внимание: OnClick = Button1Click.

Самое наверно простое поискать опенсорц компонет для свойств компонента в файл. А на его основе создать тебе клоноклепатель объектов ;) В ином случае, изучение TypInfo.pas не избежать.


 
reonid ©   (2006-07-29 00:38) [10]

procedure TForm1.btnClonePanelClick(Sender: TObject);
var stm: TStream;
begin
 stm := TMemoryStream.Create;
 try
   SaveComponentToStream(Panel1, Self, stm);
   stm.Position := 0;
   LoadComponentFromStream(Self, Self, Self, stm);
 finally
   stm.Free;
 end;
end;

{-----------------------------------------------------------}
unit Comp2Stm;

interface

uses
 Classes, Controls;

function LoadComponentFromStream(ARoot, AOwner: TComponent; AParent: TWinControl;
 SrcTxtStream: TStream; AComp: TComponent = nil): TComponent;

procedure SaveComponentToStream(AComp, ARoot: TComponent; DestTxtStream: TStream);

implementation

type
   TDummy = class
     class procedure ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
   end;

   class procedure TDummy.ReaderSetName(Reader: TReader; Component: TComponent; var Name: string);
   begin
     if (Reader.Owner <> nil) and
        (Reader.Owner.FindComponent(Name) <> nil) then Name := "";
     // Это самое простое, что можно придумать, чтобы избежать конфликта имён.
     // Всё равно в рантайме имена не слишком важны
   end;

function LoadComponentFromStream(ARoot, AOwner: TComponent; AParent: TWinControl;
 SrcTxtStream: TStream; AComp: TComponent = nil): TComponent;
var
 BinStream: TStream;
 Reader: TReader;
 Comp: TComponent;
begin
BinStream := TMemoryStream.Create;
try
  Reader := TReader.Create(BinStream, 4096);

  //SrcTxtStream.Position := 0;
  ObjectTextToBinary(SrcTxtStream, BinStream);
  try
    Reader.Position := 0;

    Reader.Owner := AOwner;
    Reader.Parent := AParent;
    Reader.Root := ARoot;
    // Владелец, родитель для создаваемого из потока
    // компонента и корневой компонент (в РТТИ-таблицах
    // которого ридер будет искать обработчики событий,
    // классы и т.д.)

    Reader.OnSetName := TDummy.ReaderSetName;
    // Для разрешения конфликтов имён

    //Reader.OnFindMethod := ;
    //Reader.OnFindComponentClass := ;

    Reader.BeginReferences;
    try
      Reader.ReadSignature;
      Comp := Reader.ReadComponent(AComp);
      Result := Comp;

      Reader.FixupReferences;
      // инициализирует свойства-ссылки на другие
      // компоненты, хранящиеся в ДФМ как имена

    finally
      Reader.EndReferences;
    end;
  finally
    Reader.Free;
  end;
finally
  BinStream.Free;
end;
end;

procedure SaveComponentToStream(AComp, ARoot: TComponent; DestTxtStream: TStream);
var BinStream: TStream;
   Writer: TWriter;
begin
 BinStream := TMemoryStream.Create();
 try
   Writer := TWriter.Create(BinStream, 4096);
   try
     Writer.Root := ARoot;
     Writer.WriteSignature;
     Writer.WriteComponent(AComp);
     Writer.WriteListEnd;

   finally
     Writer.Free;
   end;

   BinStream.Position := 0;
   ObjectBinaryToText(BinStream, DestTxtStream);
 finally
   BinStream.Free;
 end;
end;

end.


 
Piter ©   (2006-07-29 02:52) [11]

спасибо, буду разбираться.


 
Юрий Зотов ©   (2006-07-29 14:48) [12]

Может быть, просто использовать фрейм вместо панели?


 
Piter ©   (2006-07-29 16:00) [13]

Юрий Зотов ©   (29.07.06 14:48) [12]

а что там с фреймом? Я не в курсе, никогда не использовал :)


 
GrayFace ©   (2006-07-30 07:19) [14]

reonid ©   (29.07.06 0:38) [10]
TDummy

Спасибо, не знал, что можно методы класса так использовать.


 
Плохиш ©   (2006-07-31 11:23) [15]


> Юрий Зотов ©   (29.07.06 14:48) [12]

Читая 5й пост тоже самое сказать захотелось, но без вопросительного знака :-)

> Piter ©   (29.07.06 16:00) [13]
> а что там с фреймом?

Ну фреймы как раз для решения задач из [0] и предназначены :-)


 
StriderMan ©   (2006-07-31 14:13) [16]

то что лежит на панельке само в поток не сохранится. ведь у контролов, лежащих на панельке, OWNERом является не панелька, а форма.


 
Piter ©   (2006-07-31 16:15) [17]

Плохиш ©   (31.07.06 11:23) [15]
Ну фреймы как раз для решения задач из [0] и предназначены :-)


Да? Они могут копировать то, что на них лежит? Круто...
А я всегда думал - нафига нужен TFrame :)

По справке непонятно ничего :)


 
Игорь Шевченко ©   (2006-07-31 16:26) [18]


> А я всегда думал - нафига нужен TFrame


Для облегчения повторного использования кода например.


 
Piter ©   (2006-07-31 22:06) [19]

Игорь Шевченко ©   (31.07.06 16:26) [18]
Для облегчения повторного использования кода например


не понял. А можно пример?


 
tesseract ©   (2006-07-31 22:26) [20]

> [18] Игорь Шевченко ©   (31.07.06 16:26)


Я например использую его для этого оч часто.
С ними ИМХО проще, чем с репозитарием.

+ можно например между формами сохранять функциональность определённых элементов управления.


 
jack128 ©   (2006-07-31 23:22) [21]

Piter ©   (31.07.06 22:06) [19]
TFrame - компонент для ленивых. Например те нужен компонент - панель, на которой дежит кнопка. ПРи клике на этой кнопке должен появляться MessageBox - c текстом "Кликнули по кнопке". Причем такая панель должна лежать на 20 формах. Это чтож, ты ты должен 20 раз кинуть панель на формы. 20 раз на эту панель кинуть кнопку. 20 прописать обработчик события этой кнопки. Так ?  Нет, на самом деле ты жмешь New/Frame, кидаешь на этот фрейм кнопку. прописываешь обработчик клика по этой кнопке и 20 кидаешь этот фрейм на нужные формы.  В пределе - в 3 раза меньше действий. А если учесть, что кода обычно бывает не один несчастный обработчик, а 20 методов, то экономия на лицо ;-)



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

Форум: "Основная";
Текущий архив: 2006.09.10;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.51 MB
Время: 0.058 c
3-1152183559
WhiteBarin
2006-07-06 14:59
2006.09.10
Как включить логирование вIBExpert?


15-1154983441
Pascal
2006-08-08 00:44
2006.09.10
Будушее делфистов...


5-1139301255
Priest
2006-02-07 11:34
2006.09.10
Делегирование реализации интерфейсов


5-1139238792
webpauk
2006-02-06 18:13
2006.09.10
Показать поля БД


6-1145860570
cosmos
2006-04-24 10:36
2006.09.10
Ошибка подключения к Paradox через ADO





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский