KnigaRead.com/
KnigaRead.com » Компьютеры и Интернет » Программирование » Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

Валентин Озеров - Советы по Delphi. Версия 1.4.3 от 1.1.2001

На нашем сайте KnigaRead.com Вы можете абсолютно бесплатно читать книгу онлайн Валентин Озеров, "Советы по Delphi. Версия 1.4.3 от 1.1.2001" бесплатно, без регистрации.
Перейти на страницу:

interface


uses SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;


type TForm1 = class(TForm)

 Button1: TButton;

 procedure Button1Click(Sender: TObject);

private

 { Private declarations }

public

 { Public declarations }

 procedure myClick(Sender: TObject);

end;


var Form1: TForm1;


const i : integer = 0;


implementation

{$R *.DFM}


procedure TForm1.myClick(Sender: TObject);

begin

 with Sender as TButton do Self.Caption := ClassName + ' ' + Name;

end;


procedure TForm1.Button1Click(Sender: TObject);

begin

 with TButton.Create(self) do begin

  Left := 20;

  Top := 30 + i;

  Width := 120;

  Height := 40;

  Name := 'ThisButton' + IntToStr(i);

  Caption := 'There' + IntToStr(i);

  OnClick := MyClick; { процедура, определенная где-то еще }

  Parent := Form1;

 end; {end with}

 inc(i, 40);

end; {end button1.click}

end.

Решение для динамически создаваемых компонентов

Delphi 1

Предупреждение:

Если вы просто хотите во время выполнения приложения создавать компоненты необходимого вам типа, ознакомьтесь с файлом delphidocVB2Delph.wri и следуйте его рекомендациям, лучшего способа изучения этой темы пока не существует. Данный совет повествует об использовании в Delphi RTTI.

Во-первых, в вашем приложении необходимо зарегистрировать все классы, экземпляры которых вы собираетесь в каком-то месте кода создавать. Сделать это можно с помощью функций RegisterClass(), RegisterClasses() и RegisterClassAlias().

Пример:

procedure TForm1.FormCreate(Sender: TObject);

begin

 RegisterClasses([TButton, TEdit, TMemo, TLabel]);

end;

Это может навести вас на мысль об ограничениях, но Delphi строгий язык. Если вы хотите истинно динамическое создание объектов в слаботипизированной среде позднего связывания, используйте динамический язык типа Smalltalk. У меня есть подозрение, что Delphi использует этот механизм регистрации для регистрации всех компонентов в DCL при его запуске, позволяя этим самым создавать любой компонент во время разработки.

Создание компонентов. Используйте функцию FindClass() для получения ссылки на класс компонента, который вы хотите создать, и вызывайте его метод Create. Легко, не правда ли? В примере у меня имеется приведение типа SomeComponent к TControl, после чего я уже могу установить свойство parent (я могу делать это, поскольку я знаю, что все зарегистрированные мною классы являются потомками TControl). Для того, чтобы визуальный компонент появился на форме, вам необходимо установить свойство parent.

Пример:

procedure TForm1.CreateClick(Sender: TObject);

begin

 SomeComponent:= TComponentClass(FindClass(ClassName.Text)).Create(Self);

 (SomeComponent as TControl).Parent := Self;

end;

Теперь, когда вы имеете созданный компонент, как установить его свойства без использования самого большого блока case во вселенной? Очень просто: для получения информации о свойстве из структуры run-time type information (RTTI) используется функция GetPropInfo(), после чего для установления значений используется набор функций SetXXXXProp(). (Примечание: эти функции не задокументированы в файлах помощи Delphi. OO-программисты, как я понимаю, пользуются примерами из чужого кода и не изобретают свой велосипед.) У каждой функции SetXXXXProp() имеется функция-сателлит GetXXXXProp(), позволяющая узнать значения свойств объекта.

Пример:

procedure TForm1.SetPropertyClick(Sender: TObject);

var

 PropType: PTypeInfo;

 PropInfo: PPropInfo;

begin

 PropInfo := GetPropInfo(SomeComponent.ClassInfo, PropertyName.Text);

 PropType := PropInfo^.PropType;

 case PropType^.Kind of

 tkInteger:

  SetOrdProp(SomeComponent, PropInfo, StrToInt(PropertyValue.Text));

 tkChar:

  SetOrdProp(SomeComponent, PropInfo, Ord(PropertyValue.Text[1]));

 tkEnumeration:

  SetOrdProp(SomeComponent, PropInfo, GetEnumValue(PropType, PropertyValue.Text));

 tkFloat:

  SetFloatProp(SomeComponent, PropInfo, StrToFloat(PropertyValue.Text));

 tkString:

  SetStrProp(SomeComponent, PropInfo, PropertyValue.Text);

 end;

end;

Вы также можете установить значения свойств Set, Class и Method, но это будет немного сложнее. Немного позже я объясню как это можно сделать.

Это все. Вы проведете время с большой пользой, изучая исходный код VCL, и удивляясь, когда вы все там увидите собственными глазами.

Это прекрасный способ, но он имеет потенциал для массового злоупотребления. Необходимо понимание других путей достижения этой цели и выбор соответствующей техники при создании своих проектов в Delphi. 

Как правильно создавать органы управления в runtime?

Nomadic советует:

Примерно таким образом (Описываем метод-обработчик события OnClick формы):

{ Example }

procedure TForm1.OnClick(ASender: TObject);

var btnTemp: TButton;

begin

 { Creating }

 btnTemp := TButton.Create(Self);

 { You can use 'with btnTemp do' operator below }

 { Inserting to Form }

 btnTemp.Parent := Self;

 { Initialization }

 btnTemp.Caption := 'I''m glad to see You';

 btnTemp.SetBounds(20, 20, 80, 20);

 { You must define this event handler named 'OnBtnTempClick' }

 btnTemp.OnClick := OnBtnTempClick;

 { Ready to show }

 btnTemp.Visible := true;

 { Done. }

end

Как создать клон (копию, достаточно близкую к оригиналу) произвольного компонента?

Nomadic советует:

{ Здесь процедyра CreateClone, которая креатит компоненту ОЧЕНЬ ПОХОЖУЮ на входную. С такими же значениями свойств. Присваивается все, кроме методов. }

function CreateClone(Src: TComponent): TComponent;

var F: TStream;

begin

 F := nil;

 try

  F := TMemoryStream.Create;

  F.WriteComponent(Src);

  RegisterClass(TComponentClass(Src.ClassType));

  F.Position := 0;

  Result := F.ReadComponent(nil);

 finally

  F.Free;

 end;

end;

Как заставить произвольный компонент реагировать на изменения в TDataSource?

Nomadic советует:

TFieldDataLink. За D2 не скажу, а в D1 в Help'е его нет, реализован в DELPHISOURCEVCLDBTABLES.PAS.

type TMyForm = class(TForm)

 {…}

 Table1: TTable;

 DataSource1: TDataSource;

private

 FDL : TFieldDataLink;

 procedure RecChange(Sender: TObject);

public

 {...}

end;


procedure TMyForm.FormCreate(Sender: TObject);

begin

 FDL:=TFieldDataLink.Create;

 FDL.OnDataChange := RecChange;

 FDL.DataSource := DataSource1;

 FDL.FieldName := 'MyFieldName';

end;


procedure TTabEditDlg.FormDestroy(Sender: TObject);

begin

 FDL.Free;

end;


procedure TTabEditDlg.MasterChange(Sender: TObject);

begin

 {… тут реагируй на изменения …}

end;

За отслеживание различных событий, происходящих с TDataSource, в иерархии VCL отвечает класс TDataLink. TFieldDataLink – наследник, который выполняет маскирование событий, не относящихся к конкретному столбцу набора данных.

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

Доступ к другим компонентам из базового

Delphi 1 

Список-свойство Components[] существует во всех потомках TComponent и используется для хранения ссылок на все собственные компоненты. При вызове «mycomponent := TSomeComponent.Create(aComponent)», ссылка на mycomponent помещается в список aComponent Components[]. В большинстве случаев, в методе Create в качестве владельца компонентов определена форма, и ссылки на компоненты помещаются в список Components[] самой формы.

Метод FindComponent() (упомянутый где-то еще) только производит поиск компонентов в текущем списке Components[]. Если объект, который вы хотите найти, принадлежит другому компоненту, вы должны просканировать его список компонентов.

В зависимости от того, как вы создаете свою базу и другие компоненты, вы можете осуществить рекурсивный алгоритм поиска, который стартует в верхней части дерева собственника набора компонентов (вероятно, формы), спускаясь вниз и проходя по списку Components[] каждого вновь найденного компонента, пока желаемый объект не будет найден.

Перейти на страницу:
Прокомментировать
Подтвердите что вы не робот:*