![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Создание компонента
TForumHelp © (2008-05-28 16:17:00)Здравствуйте!
Возможно ли динамически создать компонент, зная только его имя (например 'TEdit' или 'TButton'), и потом управлять им, как через OLE?
чтобы получилось что-то типа:
MyButton := CreateObjectFromClass('tbutton', Form1);
MyButton.Parent := Form1;
MyButton.Left := 150;
MyButton.Top := 100;
MyButton.Caption := 'Нажми меня!';
MyButton.OnClick := MyButtonClick;
{RASkov} (2008-06-02 16:38:00) [1]> [22] TForumHelp © (02.06.08 16:24)
> а можно пожалуйста пример? :)
Объект.СвойствоОбработчикСобытия:=СовместимыйМетод;
> например: SetComponentProperty(MyControls[2], 'Caption',
> 'Push the button!');
SetPropValue
TForumHelp (2008-06-02 16:24:00) [2]
> присваиванием обработчиков соответствующим событиям
а можно пожалуйста пример? :)
и еще: можно ли какой-то функцией присвоить любомуTComponentзначение любому из его свойств, типа:
function SetComponentProperty(var Component: TComponent; PropertyName, PropertyValue: String): Boolean;
например:SetComponentProperty(MyControls[2], 'Caption', 'Push the button!');
icWasya (2008-06-02 14:33:00) [3]Изучать Classes.pas
посмотри как сделан ReadComponent
Palladin (2008-06-02 11:05:00) [4]присваиванием обработчиков соответствующим событиям
TForumHelp (2008-05-31 12:46:00) [5]У меня еще один вопрос: как обрабатывать сообщения для созданного
Controls[High(Controls)], на подобиеMouseEnter, MouseLeave, MouseDown, MouseUpитд?
TForumHelp (2008-05-31 11:44:00) [6]
> // не совсем понятно, на кой черт создавать на разные классы
> разные массивы
это делается для редактирования свойств в будующем и присваивания процедур.
Palladin (2008-05-30 10:15:00) [7]
> TForumHelp © (30.05.08 07:33) [16]
во первых откажись от dll и уйди на bpl, от dll тебе никакого проку нет, а вот RTTI будет уже общее, это раз. два. так как у тебя будет bpl. ты спокойным образом сможешь передавать в функцию не имя классаконтрола, а ссылку на классконтрола. и делается это так:
procedure DrawComponent(var Parent: TWinControl; CtrlClass:TWinControlClass; ConstClassData: 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-30 07:33:00) [8]То есть я прошу чего-то нереального?... =( очень жаль.
Придется работать с примером в [10]...
DimaBr (2008-05-29 12:06:00) [9]> {RASkov}
Он просто ещё не натыкался на эти грабли
{RASkov} (2008-05-29 11:53:00) [10]Помоему тебе нужно в сторону БПЛ смотреть, иначе никак.... в длл и екзэ классы разные, хоть и одинаковые имена имеют...
TForumHelp (2008-05-29 11:32:00) [11]
> должен быть в екзэ или длл...
в exe он итак есть. через dll просто вызывается.
{RASkov} (2008-05-29 11:27:00) [12]> [8] TForumHelp © (29.05.08 10:41)
> чтобы не добавлять модули Messages, Classes, Graphics, Controls,
> Forms, Dialogs, StdCtrls, ..., которые значительно увеличат размер
> библиотеки - нужно создавать их через "имя класса".
Это не возможно! Код создаваемого компонента, пусть хоть через имя класса, должен быть в екзэ или длл...
Так, что подключать все равно придеться модули с кодом компонентов, которые нужно потом в программе создавать...
DimaBr (2008-05-29 11:09:00) [13]Начнём с начала и помедленнее.
Вы хотите создавать динамически компоненты из некоего файла (базы).
Для этого необходимо зарегистрировать данные классы и тогда они скомпилятся в вашу EXE-шку и и Вы сможете создавать те классы которые зарегистрированны.
Иначе, допустим вы придумали механизм создания любого объекта без его компиляции. Первый же ворос, а как проинициализируются свойства в конструкторе если конструктор нескомпилирован ???
TForumHelp (2008-05-29 10:50:00) [14]
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 я тоже пробовал создавать, но, как я уже говорил, я подразумеваю создание большого количества компонентов.
TForumHelp (2008-05-29 10:42:00) [15]
> Возможно ли динамически создать компонент, зная только его
> имя(например 'TEdit' или 'TButton'), и потом управлять
> им, как через OLE?
вот тут оговорился - извините.
Имелось ввиду имя класса!
TForumHelp (2008-05-29 10:41:00) [16]Программа динамически подгружает 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).
Olegz77 (2008-05-28 21:23:00) [17]Запарненько это, если хочешь работать с любыми компонентами, созданными по имени класса, да еще и без приведения типа. Думаю, что это можно сделать, создав компонент, поддерживающий интерфейс IDispatch, но это все запа-а-арненько. Поищи статью Анатолия Тенцера про использование ActiveX компонента Microsoft Script Control. Там много есть, что пригодится
{RASkov} (2008-05-28 18:05:00) [18]> [4] TForumHelp © (28.05.08 17:23)
Наверное весж лучше расскажи задачу в целом..... иначе кажется что ты хочешь "не возможного" :)
Reindeer Moss Eater (2008-05-28 17:27:00) [19]а если я создам TButton, который имеет свойство Caption?
И чего? Создай.
TForumHelp (2008-05-28 17:23:00) [20]а если я создам
TButton, который имеет свойствоCaption?TControlClass(C).Create(self)не имеет этого свойства. Можно ли как-то по-другому это сделать (без регистрации итп)?