Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Динамичное создение контролов


Strate ©   (2007-05-09 21:17:00) 

Создаю чекбокс на форме:

chkBoxes[0] := TCheckBox.Create(Self);

... дальше выставляю Parent, Visible... в общем контрол создаётся и работает.

Тут же:

chkBoxes[0].Free - и уже выдаёт ошибку Invalid Pointer Operation.

В чём проблема?


Strate   (2007-05-09 22:25:00) [1]

В общем пропала ошибка :) Всё клёво работает. Вот изменённые участки:

procedure TfrmQuery.DestroyComponents;
var
 i : byte;
begin
 for i := 0 to High(chkFields) do
   FreeAndNil(chkFields[i]);
end;


procedure TfrmQuery.FormShow(Sender: TObject);
var
 i : byte;
 Fields : TStringList;
begin
 Fields := TStringList.Create;
 Table.GetFieldNames(Fields);
 SetLength(chkFields, Fields.Count);
 for i := 0 to Fields.Count-1 do
 begin
   chkFields[i] := TCheckBox.Create(Self);
   With chkFields[i] do
   begin
     Height := 25;
     Parent := Self;
     Visible := True;
     Caption := Fields[i];
     Left := 10;
     Top := 10+(Height+10)*i;
   end;
 end;
 Fields.Free;
end;


Johnmen   (2007-05-09 22:23:00) [2]


>  теперь ошибка сразу на первом вызове chkFields[i].Free;

Индексация динамических массивов начинается с нуля. О чём и написано в хелпе.


Strate   (2007-05-09 22:21:00) [3]

Подправил вот до такого состояния:

procedure TfrmQuery.FormShow(Sender: TObject);
var
 i : byte;
 Fields : TStringList;
begin
 Fields := TStringList.Create;
 Table.GetFieldNames(Fields);
 SetLength(chkFields, Fields.Count);
 for i := 0 to Fields.Count-1 do
 begin
   chkFields[i+1] := TCheckBox.Create(Self);
   With chkFields[i+1] do
   begin
     Height := 25;
     Parent := Self;
     Visible := True;
     Caption := Fields[i];
     Left := 10;
     Top := 10+(Height+10)*i;
   end;
 end;
 Fields.Free;
end;


, теперь ошибка сразу на первом вызове chkFields[i].Free;


Johnmen   (2007-05-09 22:21:00) [4]


> Ну, пока я тестирую полей больше чем 1 и они всегда есть :)

Т.е. кол-во элементов массива меньше кол-ва полей, и это нормально???


Johnmen   (2007-05-09 22:19:00) [5]


>> for i := 0 to High(chkFields) do
>>  chkFields[i].Free;
> А ты уверен, что в массиве вообще есть элементы???

Здесь нормально...


Strate   (2007-05-09 22:18:00) [6]

Johnmen ©   (09.05.07 22:14) [6]

Ну, пока я тестирую полей больше чем 1 и они всегда есть :) Исправил немного:

procedure TfrmQuery.DestroyComponents;
var
 i : byte;
begin
 for i := 0 to Length(chkFields) do
   FreeAndNil(chkFields[i]);
end;

Но ошибка после закрытия главной формы никуда не делась. И возникает она вообще после оператора Application.Run (после его выполнения) :-(


Johnmen   (2007-05-09 22:14:00) [7]


> SetLength(chkFields, Fields.Count-1);

Т.е. если поле одно, то размерность массива = 0 ? :)))

for i := 0 to High(chkFields) do
  chkFields[i].Free;

А ты уверен, что в массиве вообще есть элементы???


Strate   (2007-05-09 22:05:00) [8]

т.е. не при нажатии на кнопку. После закрытия формы пытаюсь закрыть главную форму - и выскакивает Invalid Pointer Operation.

Если убрать всё что связано с динамическими чекбоксами всё нормально.


Strate   (2007-05-09 22:01:00) [9]

Вот полностью код:

TfrmQuery = class(TForm)
   cmdOK: TButton;
   cmdClose: TButton;
   Button1: TButton;
   procedure cmdCloseClick(Sender: TObject);
   procedure cmdOKClick(Sender: TObject);
   procedure FormShow(Sender: TObject);
   procedure Button1Click(Sender: TObject);
 private
   { Private declarations }
   Cancelled : boolean;
   Table : TADOTable;
   procedure DestroyComponents;
 public
   { Public declarations }
   chkFields : array of TCheckBox;
   function ShowDialog (ATable : TADOTable) : integer;
 end;

var
 frmQuery: TfrmQuery;

implementation

{$R *.dfm}

procedure TfrmQuery.DestroyComponents;
var
 i : byte;
begin
 for i := 0 to High(chkFields) do
   chkFields[i].Free;
end;

function TfrmQuery.ShowDialog;
begin
 result := 1;
 Cancelled := True;
 Table := ATable;
 ShowModal;
 If Cancelled then result :=0;
end;

procedure TfrmQuery.cmdCloseClick(Sender: TObject);
begin
 Cancelled := True;
 Close;
end;

procedure TfrmQuery.cmdOKClick(Sender: TObject);
begin
 Cancelled := False;
 Close;
end;

procedure TfrmQuery.FormShow(Sender: TObject);
var
 i : byte;
 Fields : TStringList;
begin
 Fields := TStringList.Create;
 Table.GetFieldNames(Fields);
 SetLength(chkFields, Fields.Count-1);
 for i := 0 to Fields.Count-1 do
 begin
   chkFields[i] := TCheckBox.Create(Self);
   With chkFields[i] do
   begin
     Height := 25;
     Parent := Self;
     Visible := True;
     Caption := Fields[i];
     Left := 10;
     Top := 10+(Height+10)*i;
   end;
 end;
 Fields.Free;
end;

procedure TfrmQuery.Button1Click(Sender: TObject);
begin
 DestroyComponents;
end;


Из другой формы вызывается ShowDialog, создаются контролы и работают. Жмём на Button1 - вываливается ошибка.


Rial   (2007-05-09 21:45:00) [10]

> [0] Strate ©   (09.05.07 21:17)
> Тут же:

Замени "тут же" на реальный код.


Johnmen   (2007-05-09 21:37:00) [11]

При указанных исходных данных ошибки не будет, если N>0.


Strate   (2007-05-09 21:22:00) [12]

Да, ещё забыл уточнить.

chkBoxes : array of TCheckBox;

длину выставляю перед созданием

SetLength(chkBoxes, N);


Наверх

Титульная страница Поиск, карта сайта Написать письмо