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

Вниз

Создание компонента   Найти похожие ветки 

 
TForumHelp ©   (2008-05-28 16:17) [0]

Здравствуйте!

Возможно ли динамически создать компонент, зная только его имя (например "TEdit" или "TButton"), и потом управлять им, как через OLE?

чтобы получилось что-то типа:
MyButton := CreateObjectFromClass("tbutton", Form1);
MyButton.Parent := Form1;
MyButton.Left := 150;
MyButton.Top := 100;
MyButton.Caption := "Нажми меня!";
MyButton.OnClick := MyButtonClick;


 
TForumHelp ©   (2008-05-28 16:19) [1]

Кстати, я подразумеваю создание не только стандартных компонентов, но и своих собственных!

Заранее спасибо!


 
Reindeer Moss Eater ©   (2008-05-28 16:28) [2]

и потом управлять им, как через OLE?

А почему не по infra red?


 
DimaBr ©   (2008-05-28 16:32) [3]

Для этого нужно зарегистрировать компонент

procedure TForm1.Button1Click(Sender: TObject);
var C: TPersistentClass;
begin
 C := FindClass("TPanel");
 if Assigned(C) then begin
   TControlClass(C).Create(self).Parent := form1 ;
 end;
end;

initialization
 RegisterClass(TPanel);


 
TForumHelp ©   (2008-05-28 17:23) [4]

а если я создам TButton, который имеет свойство Caption? TControlClass(C).Create(self) не имеет этого свойства. Можно ли как-то по-другому это сделать (без регистрации итп)?


 
Reindeer Moss Eater ©   (2008-05-28 17:27) [5]

а если я создам TButton, который имеет свойство Caption?

И чего? Создай.


 
{RASkov} ©   (2008-05-28 18:05) [6]

> [4] TForumHelp ©   (28.05.08 17:23)

Наверное весж лучше расскажи задачу в целом..... иначе кажется что ты хочешь "не возможного" :)


 
Olegz77 ©   (2008-05-28 21:23) [7]

Запарненько это, если хочешь работать с любыми компонентами, созданными по имени класса, да еще и без приведения типа. Думаю, что это можно сделать, создав компонент, поддерживающий интерфейс IDispatch, но это все запа-а-арненько. Поищи статью Анатолия Тенцера про использование ActiveX компонента Microsoft Script Control. Там много есть, что пригодится


 
TForumHelp ©   (2008-05-29 10:41) [8]

Программа динамически подгружает Dll, через который осуществляется "отрисовка" компонентов на компоненте, переданом плагину.

procedure DrawComponents(var Parent: TWinControl);

чтобы не добавлять модули Messages, Classes, Graphics, Controls, Forms,
 Dialogs, StdCtrls, ...
, которые значительно увеличат размер библиотеки - нужно создавать их через "имя класса".

Я пытался уже сделать таким образом:


var
 S: String;

function ComponentToString(Component: TComponent): String;
function StringToComponent(Component: String): TMemoryStream;

implementation


S имеет значение:

object MyButton: TButton
     Left = 5
     Top = 5
     Width = 75
     Height = 25
     Caption = "Button"
     TabOrder = 2
end


теперь ф-и:

function ComponentToString(Component: TComponent): String;
var
 MS: TMemoryStream;
 SS: TStringStream;
 S: String;
begin
 MS := TMemoryStream.Create;
 MS.WriteComponent(Component);
 MS.Seek(0, soFromBeginning);
 SS := TStringStream.Create(S);
 ObjectBinaryToText(MS, SS);
 Result := SS.DataString;
end;

function StringToComponent(Component: String): TMemoryStream;
var
 MS: TMemoryStream;
 SS: TStringStream;
 S: String;
begin
 MS := TMemoryStream.Create;
 S := Component;
 SS := TStringStream.Create(S);
 ObjectTextToBinary(SS, MS);
 MS.SaveToFile("component.dat");//без файла работать не хочет
 MS.Free;
 MS := TMemoryStream.Create;
 MS.LoadFromFile("component.dat");
 DeleteFile("component.dat");
 Result := MS;
end;


теперь использование:

 StringToComponent(S).ReadComponent(Button1);


Каким-то образом нужно создать компонент, который "получит" наши параметры (на примере Button1).


 
TForumHelp ©   (2008-05-29 10:42) [9]


> Возможно ли динамически создать компонент, зная только его
> имя
(например "TEdit" или "TButton"), и потом управлять
> им, как через OLE?


вот тут оговорился - извините.

Имелось ввиду имя класса!


 
TForumHelp ©   (2008-05-29 10:50) [10]

var
 Buttons: array of TButton;
 CButtons: Integer;
 Edits: array of TEdit;
 CEdits: Integer;
 ClassName: String;
 ClassData: String;


на примере: ClassName = "TButton";, а ClassData =
"object MyButton: TButton
    Left = 5
    Top = 5
    Width = 75
    Height = 25
    Caption = "Button"
    TabOrder = 2
end";

обрабатываем:

procedure DrawComponent(var Parent: TWinControl; ClassName, ClassData: String);
begin
 If LowerCase(ClassName) = "tbutton" then begin
   Inc(CButtons);
   SetLength(Buttons, CButtons+1);
   Buttons[CButtons] := TButton.Create(Parent);
   Buttons[CButtons].Parent := Parent;
   StringToComponent(ClassData).ReadComponent(Buttons[CButtons]);
 end else
 If LowerCase(ClassName) = "tedit" then begin
   Inc(CEdits);
   SetLength(Edits, CEdits+1);
   Edits[CEdits] := TEdits.Create(Parent);
   Edits[CEdits].Parent := Parent;
   StringToComponent(ClassData).ReadComponent(Edits[CEdits]);
 end else
 If LowerCase(ClassName) = "t..." then begin

 end else
 begin
   //другой
 end;
end;

 

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

Через WinApi я тоже пробовал создавать, но, как я уже говорил, я подразумеваю создание большого количества компонентов.


 
DimaBr ©   (2008-05-29 11:09) [11]

Начнём с начала и помедленнее.
Вы хотите создавать динамически компоненты из некоего файла (базы).
Для этого необходимо зарегистрировать данные классы и тогда они скомпилятся в вашу EXE-шку и и Вы сможете создавать те классы которые зарегистрированны.
Иначе, допустим вы придумали механизм создания любого объекта без его компиляции. Первый же ворос, а как проинициализируются свойства в конструкторе если конструктор нескомпилирован ???


 
{RASkov} ©   (2008-05-29 11:27) [12]

> [8] TForumHelp ©   (29.05.08 10:41)
> чтобы не добавлять модули Messages, Classes, Graphics, Controls,
> Forms, Dialogs, StdCtrls, ..., которые значительно увеличат размер
> библиотеки - нужно создавать их через "имя класса".

Это не возможно! Код создаваемого компонента, пусть хоть через имя класса, должен быть в екзэ или длл...
Так, что подключать все равно придеться модули с кодом компонентов, которые нужно потом в программе создавать...


 
TForumHelp ©   (2008-05-29 11:32) [13]


> должен быть в екзэ или длл...

в exe он итак есть. через dll просто вызывается.


 
{RASkov} ©   (2008-05-29 11:53) [14]

Помоему тебе нужно в сторону БПЛ смотреть, иначе никак.... в длл и екзэ классы разные, хоть и одинаковые имена имеют...


 
DimaBr ©   (2008-05-29 12:06) [15]

> {RASkov}
Он просто ещё не натыкался на эти грабли


 
TForumHelp ©   (2008-05-30 07:33) [16]

То есть я прошу чего-то нереального?... =( очень жаль.

Придется работать с примером в [10]...


 
Palladin ©   (2008-05-30 10:15) [17]


> TForumHelp ©   (30.05.08 07:33) [16]

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

procedure DrawComponent(var Parent: TWinControl; CtrlClass:TWinControlClass;Const ClassData: String);
begin
// не совсем понятно, на кой черт создавать на разные классы разные массивы
SetLength(Controls, Length(Controls)+1);
Controls[High(Controls)] := CtrlClass.Create(Parent);
Controls[High(Controls)].Parent := Parent;
StringToComponent(ClassData).ReadComponent(Controls[High(Controls)]);
end;


 
TForumHelp ©   (2008-05-31 11:44) [18]


> // не совсем понятно, на кой черт создавать на разные классы
> разные массивы


это делается для редактирования свойств в будующем и присваивания процедур.


 
TForumHelp ©   (2008-05-31 12:46) [19]

У меня еще один вопрос: как обрабатывать сообщения для созданного Controls[High(Controls)], на подобие MouseEnter, MouseLeave, MouseDown, MouseUp итд?


 
Palladin ©   (2008-06-02 11:05) [20]

присваиванием обработчиков соответствующим событиям


 
icWasya ©   (2008-06-02 14:33) [21]

Изучать Classes.pas
посмотри как сделан ReadComponent


 
TForumHelp ©   (2008-06-02 16:24) [22]


> присваиванием обработчиков соответствующим событиям

а можно пожалуйста пример? :)

и еще: можно ли какой-то функцией присвоить любому TComponent значение любому из его свойств, типа:

function SetComponentProperty(var Component: TComponent; PropertyName, PropertyValue: String): Boolean;

например: SetComponentProperty(MyControls[2], "Caption", "Push the button!");


 
{RASkov} ©   (2008-06-02 16:38) [23]

> [22] TForumHelp ©   (02.06.08 16:24)
> а можно пожалуйста пример? :)

Объект.СвойствоОбработчикСобытия:=СовместимыйМетод;

> например: SetComponentProperty(MyControls[2], "Caption",
> "Push the button!");

SetPropValue



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

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

Наверх




Память: 0.53 MB
Время: 0.011 c
15-1245521182
Kerk
2009-06-20 22:06
2009.08.23
География


2-1245244901
TheEd
2009-06-17 17:21
2009.08.23
Странное поведение ShowModal...


15-1245486265
TCrash
2009-06-20 12:24
2009.08.23
Органайзер/календарь


15-1245949320
Илья_
2009-06-25 21:02
2009.08.23
Сборка компьютера


6-1200297698
JanMihail
2008-01-14 11:01
2009.08.23
Как подождать загрузки WebBrowser a