Форум: "Основная";
Текущий архив: 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.006 c