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

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.51 MB
Время: 0.005 c
2-1245902081
Abcdef123
2009-06-25 07:54
2009.08.23
Как сравнить два списка (массива)?


15-1245496380
Palladin
2009-06-20 15:13
2009.08.23
Это не цикл это рекурсия


15-1245961803
Юрий
2009-06-26 00:30
2009.08.23
С днем рождения ! 26 июня 2009 пятница


2-1245832136
Алексс
2009-06-24 12:28
2009.08.23
Хранимые процедуры


15-1245616201
Юрий
2009-06-22 00:30
2009.08.23
С днем рождения ! 22 июня 2009 понедельник





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский