Недавно добавленные исходники

•  DeLiKaTeS Tetris (Тетрис)  4 427

•  TDictionary Custom Sort  6 457

•  Fast Watermark Sources  6 241

•  3D Designer  9 202

•  Sik Screen Capture  6 588

•  Patch Maker  6 980

•  Айболит (remote control)  6 975

•  ListBox Drag & Drop  5 844

•  Доска для игры Реверси  96 955

•  Графические эффекты  7 179

•  Рисование по маске  6 478

•  Перетаскивание изображений  5 344

•  Canvas Drawing  5 713

•  Рисование Луны  5 424

•  Поворот изображения  4 960

•  Рисование стержней  3 523

•  Paint on Shape  2 793

•  Генератор кроссвордов  3 661

•  Головоломка Paletto  2 952

•  Теорема Монжа об окружностях  3 760

•  Пазл Numbrix  2 478

•  Заборы и коммивояжеры  3 163

•  Игра HIP  2 127

•  Игра Go (Го)  2 060

•  Симулятор лифта  2 421

•  Программа укладки плитки  2 108

•  Генератор лабиринта  2 567

•  Проверка числового ввода  2 258

•  HEX View  2 584

•  Физический маятник  2 200

 
скрыть

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



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

Если вы просто хотите во время выполнения приложения создавать компоненты необходимого вам типа, ознакомьтесь с файлом delphi\doc\VB2Delph.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.