![]() |
|
|
|||||||
| Регистрация | << Правила форума >> | FAQ | Пользователи | Календарь | Поиск | Сообщения за сегодня | Все разделы прочитаны |
![]() |
|
|
Опции темы | Поиск в этой теме | Опции просмотра |
|
#1
|
|||
|
|||
|
Есть окно с одним tabsheet. На этот tabsheet программист ручками кидает произвольное число контролов (поля ввода чисел, строк, разные "галочки" и т.д.) со своими свойствами (в частности, эвентом OnChange, ссылающимся на определенные процедуры обработки).
Нужно программно сгенерировать определенное число tabsheets, куда программно скопировать контролы с первого tabsheet (визуально выглядящие и находящиеся на тех же местах, как и на первом tabsheet). Смысл в том, чтобы вводить через разные однотипные контролы в разных однотипных tabsheets данные в массивы параметров. Как это можно сделать? Попробовал сделать так: Код:
for i := 0 to TabSheet16.ComponentCount - 1 do
begin
contr := TCustomControl.Create(self);
contr.Assign(TabSheet16.Components[i] as TCustomControl);
contr.Parent := TabSheet17;
end;![]() Последний раз редактировалось Martin, 10.02.2017 в 19:06. |
|
#2
|
|||
|
|||
|
Заставить программиста "кидать" контролы на фрейм, а потом в ран-тайм просто создавать фрейм целиком и "класть" его на табшит.
|
|
#3
|
||||
|
||||
|
В моем примере контролы одной панели полностью копируются на вторую панель.
Код:
uses
TypInfo;
procedure CopyObject(ObjFrom, ObjTo: TObject);
var
PropInfos: PPropList;
PropInfo: PPropInfo;
Count, Loop: Integer;
OrdVal: Longint;
StrVal: String;
FloatVal: Extended;
MethodVal: TMethod;
begin
Count := GetPropList(ObjFrom.ClassInfo, tkAny, nil);
GetMem(PropInfos, Count * SizeOf(PPropInfo));
try
GetPropList(ObjFrom.ClassInfo, tkAny, PropInfos);
for Loop := 0 to Count - 1 do
begin
PropInfo := GetPropInfo(ObjTo.ClassInfo, PropInfos^[Loop]^.Name);
case PropInfos^[Loop]^.PropType^.Kind of
tkInteger, tkChar, tkEnumeration,
tkSet, tkClass{$ifdef Win32}, tkWChar{$endif}:
begin
OrdVal := GetOrdProp(ObjFrom, PropInfos^[Loop]);
if Assigned(PropInfo) then
SetOrdProp(ObjTo, PropInfo, OrdVal);
end;
tkFloat:
begin
FloatVal := GetFloatProp(ObjFrom, PropInfos^[Loop]);
if Assigned(PropInfo) then
SetFloatProp(ObjTo, PropInfo, FloatVal);
end;
{$ifndef DelphiLessThan3}
tkWString,
{$endif}
{$ifdef Win32}
tkLString,
{$endif}
tkString:
begin
{ components must have unique names }
if UpperCase(PropInfos^[Loop]^.Name) = 'NAME' then
Continue;
StrVal := GetStrProp(ObjFrom, PropInfos^[Loop]);
if Assigned(PropInfo) then
SetStrProp(ObjTo, PropInfo, StrVal);
end;
tkMethod:
begin
MethodVal := GetMethodProp(ObjFrom, PropInfos^[Loop]);
if Assigned(PropInfo) then
SetMethodProp(ObjTo, PropInfo, MethodVal);
end
end
end
finally
FreeMem(PropInfos, Count * SizeOf(PPropInfo));
end;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Original, Clone: TControl;
OriginalClass: TClass;
i: integer;
begin
for i := 0 to Panel1.ControlCount - 1 do
begin
Original := Panel1.Controls[i];
OriginalClass := Original.ClassType;
Clone := TControlClass(OriginalClass).Create(Original.Owner);
Clone.Parent := Panel2;
CopyObject(Original, Clone);
end;
end;Для изучения: RTTI |
|
#4
|
||||
|
||||
|
Цитата:
![]() |
|
#5
|
|||
|
|||
|
Цитата:
Я тоже сначала подумал о честном копировании. Остановили меня 2 вещи: 1. В конце указано зачем это надо. Т.е. задача не скопировать контролы, а минимизировать ручную работу при разработке. 2. Там что-то говорилось про обработчики событий. А вот это уже road block для простого копирования, т.к. скорее всего обработчик завязан на конкретный контрол. Мало кто пишет обработчики без прямой адресации контролов с самого начала. Соответственно, фрейм более универсальное решение в таком случае. |
|
#6
|
||||
|
||||
|
Цитата:
П.2 - Тут абсолютно согласен. Если в методе контрола идет работа с неабстрагированным контролом, то и клон будет работать с теми же контролами. А посоветовать фреймы мне показалось очень банальным Да и ты уже их посоветовал ![]() Последний раз редактировалось dr. F.I.N., 11.02.2017 в 11:46. |
|
#7
|
|||
|
|||
|
Всем спасибо, использовал TabControl.
|