Жизнь и смерть в режиме RunTime на KOL

В этом разделе у нас будет немного мистики и чертовщины (Кнопки и прочие контролы интерфейса будут возникать и пропадать неоткуда). В общем если вы немного Гарри Потерр данный монолог будет вам интересен :)

В форуме уже звучали вопросы про "динамическое" создание кнопок. Если ваш проект на VCL то глоток знаний по данному вопросу можно получить на сайте Королевство DELPHI в статья "Жизнь и смерть в режиме run-time" (надеюсь автор статьи не обвинит меня в плагиате).
Рекомендую вам прочесть данный опус для общего развития и потому что фактически все ниже изложенное вытекает из этого произведения.

Что бы понять отличия от VCL в данном вопросе надо уяснить 2 вещи :

У объектов нет свойства Name (поэтому вы не сможете их искать через FindComponent)
Все изменения вытекают из 1-го пункта :)
При создание объекта на уже работающем окне вам кроме обычного конструктора надо сделать обращение к CreateWindow.
Пример :
// form - родительский объект на котором создается контрол  
NewBigButton := NewButton(form,'КНОПКА');  
NewBigButton.CreateWindow;  

Если все нормально CreateWindow возвращает true. Так что если вы "правильный" программист неплохо бы эту функцию вызывать c проверкой через IF.

"Родительский" объект "нумерует" все объекты которые вы создаете на нем.
Для того что бы узнать под каким номером идет ваш "дочерний" объект нужно обратившись к свойству ChildIndex. А если вам известен номер "дочернего" объекта то вы сможете обратится к нему через свойство Children.
Пример :
var  
i:integer;  
...  
  
// form - родительский объект  
NewBigButton := NewButton(form,'КНОПКА');  
NewBigButton.CreateWindow;  
  
i := form.ChildIndex(NewBigButton) // получаем номер объекта  
form.Children(i).caption := ' Это кнопка' // обращаемся к тому же NewBigButton  

Количество дочерних объектов узнается с помощью ChildCount. Таким образом можно устроить "перебор" всех дочерних объектов определенного контрола.

Наверное у некоторых читателей может возникнуть вопрос: к чему мне все эти "номера дочерних объектов"?
Ответ на вопрос лежит на поверхности. Если вы создаете ваши контролы динамически(их количество не определено заранее) вы не сможете обратится к ним другим способом только как через его номер.
При этом надо учесть что номера объектов сдвигается если ранее созданный объект удален.

Для того что бы создаваемые вами визуальные объекты имели дополнительную информацию можно использовать свойство Tag. В него можно заносить любое целое число. В ниже приведенном примере в Tag заносится константа которая указывает на "функциональный тип" объекта (кнопка, EditBox и т.д.)
program Primer13;   
   
uses   
  kol,   
  messages,   
  windows;   
   
{$R *.RES}   
var   
 form,butNewElement,lebDel,edNoDel,butDelElement,gb,   
 rbButton,rbEditBox,rbRadioBox,rbCheckBox:pControl;   
 new:pControl;   
 Nomer:integer;   
   
const   
 cButton=1;   
 cEditBox=2;   
 cRadioBox=3;   
 cCheckBox=4;   
   
procedure ClickElemet( Dummy : Pointer; Sender: PControl );   
begin   
 case Sender.Tag of   
  cButton:ShowMessage('Нажата кнопка - № '+Int2Str(form.ChildIndex(Sender)));   
  cRadioBox:ShowMessage('Нажата RadioBox - № '+Int2Str(form.ChildIndex(Sender)));   
  cCheckBox:ShowMessage('Нажат CheckBox - № '+Int2Str(form.ChildIndex(Sender)));   
 end;{case}   
end;   
   
Procedure ClickButMakeButton ( Dummy : Pointer; Sender : PControl );   
begin   
 // Фактически самая главная функция.   
 // В зависимости от того какой RadioBox выбран создаем   
 // определенного вида объект   
   
 if rbButton.Checked then   
  begin   
   new:= NewButton(form,'');   
   new.Width := 100;   
   new.Caption := 'Button №'+int2Str(form.ChildIndex(new));   
   new.Tag := cButton;   
  end   
 else   
 if rbEditBox.Checked then   
  begin   
   new:= NewEditBox(form,[]);   
   new.Text :='EditBox №'+int2Str(form.ChildIndex(new));   
   new.Tag := cEditBox;   
  end   
 else   
 if rbRadioBox.Checked then   
  begin   
   new:= NewRadioBox(form,'');   
   new.Caption := 'RadioBox №'+int2Str(form.ChildIndex(new));   
   new.Width := 100;   
   new.Tag := cRadioBox;   
  end   
 else   
 if rbCheckBox.Checked then   
  begin   
   new:= NewCheckBox(form,'');   
   new.caption := 'CheckBox №'+int2Str(form.ChildIndex(new));   
   new.Width := 100;   
   new.Tag := cCheckBox;   
  end;   
   
 new.CreateWindow;   
   
 // ------- располагаем по красивее новый контрол -------   
 new.Left:= 10;   
 inc(Nomer);   
 // так как все 4 элемента имеют одинаковую высоту...   
 new.Top := Nomer*new.Height;   
 // ------------------------------------------------------   
   
 new.OnClick := TOnEvent(MakeMethod(nil,@ClickElemet));   
end;   
//////////////////////////////////////////////////////////////////////////   
procedure ClickDelElemet( Dummy : Pointer; Sender: PControl );   
begin   
 form.Children[Str2Int(edNoDel.Text)].free;   
end;   
//////////////////////////////////////////////////////////////////////////   
begin   
 Applet := NewApplet('RunTime');   
 Applet.Font.FontName := 'Arial';   
 Applet.Font.FontWidth := 15;   
 form:=NewForm(Applet,'Создание в режиме RunTime элементов интерфейса').SetSize(600,450);   
 form.CenterOnParent;   
   
//--------------------------- рисуем интерфейс ---------------------------   
 gb := NewGroupBox(form,'Выберите').SetAlign(caRight);   
 gb.Width := 100;   
   
 rbButton  := NewRadioBox(gb,'Button').SetAlign(caTop);   
 rbEditBox := NewRadioBox(gb,'EditBox').SetAlign(caTop);   
 rbRadioBox:= NewRadioBox(gb,'RadioBox').SetAlign(caTop);   
 rbCheckBox:= NewRadioBox(gb,'CheckBox').SetAlign(caTop);   
   
 // главная кнопка   
 butNewElement := NewButton(gb,'Создать');   
 butNewElement.Width := 110;   
 butNewElement.Align := caTop;   
 butNewElement.OnClick := TOnEvent( MakeMethod( nil, @ClickButMakeButton ) );   
   
 butDelElement :=NewButton(gb,'Удалить').SetAlign(caBottom);   
 butDelElement.OnClick := TOnEvent( MakeMethod( nil, @ClickDelElemet));   
 edNoDel := NewEditBox(gb,[]).SetAlign(caBottom);   
 edNoDel.Text := '1';   
 lebDel := NewWordWrapLabel(gb,'Номер удаляемого элемента').SetAlign(caBottom);   
 //------------------------------------------------------------------------   
   
 run(Applet);   
end.   

Размер кода 3,3 Кб. Размер программы 31,5 Кб (без сжатия и замены модулей).

P.S.
Уже когда все было написано Дмитрий Жаров aka Gandalf внес замечание по поводу того что (далее идет цитата)

>1) Есть Tag, ему можно присвоить PChar, вот так:
>obj1.Tag := Integer( 'Obj1' );

(это вырезка из переписки Gandalf с Кладовым)
Мысль очень не плохая так как дает возможность назначать контролам имена и делать поиск по ним.
Теги:
RunTime
Добавлено: 13 Июля 2018 08:10:08 Добавил: Андрей Ковальчук Нравится 0
Добавить
Комментарии:
Нету комментариев для вывода...