Урок 13 - Жизнь и смерть в режиме RunTime на KOL
Ведущий раздела KOL и MCK: Анатолий aka XVeL
Автор: Борис Моренко
WEB-сайт: http://kol.mastak.ru
Полную версию библиотеки KOL и MCK можно скачать здесь.
13 урок... Если вы суеверный можете не читать :) В этом разделе у нас
будет немного мистики и чертовщины (Кнопки и прочие контролы интерфейса
будут возникать и пропадать неоткуда). В общем если вы немного Гарри
Потерр данный монолог будет вам интересен :)
В форуме уже звучали вопросы про "динамическое" создание кнопок. Если
ваш проект на 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 с Кладовым) Мысль очень не плохая так как дает
возможность назначать контролам имена и делать поиск по
ним.
|