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

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

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

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

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

  1. У объектов нет свойства Name (поэтому вы не сможете их искать через FindComponent)
  2. Все изменения вытекают из 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 с Кладовым)
Мысль очень не плохая так как дает возможность назначать контролам имена и делать поиск по ним.

Источник: http://bonanzas.rinet.ru , http://kol.mastak.ru



Опубликовал admin
5 Май, Понедельник 2003г.
ФК "Анжи": Егоров рассудит "Анжи" и "Локомотив".


Программирование для чайников.