Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > IT форум > Помощь студентам
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 16.12.2012, 19:04   #1
Andr_XxX
Новичок
Джуниор
 
Регистрация: 16.12.2012
Сообщений: 2
Вопрос Удаление элементов из динамического массива (Delphi XE3)

Здравствуйте, уважаемыепрограммисты!
Столкнулся с такой проблемой:
Необходимо реализовать функцию удаления картинок (TImg) из контекстного меню.
Имеется 2 юнита. Главный и для работы с картинками:

Код:
unit Unit1;
interface
uses
  Unit2,
  Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics,
  Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.Menus;
type
  TForm1 = class(TForm)
    aBlocksPM: TPopupMenu;
    Del: TMenuItem;
    procedure PPBtn_DelBlckClick(Sender: TObject);
    procedure FormCreate(Sender: TObject);
    procedure FormMouseDown(Sender: TObject; Button: TMouseButton;Shift:TShiftState; X, Y: Integer);
  private
  public
    n: aBlocks;
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.FormCreate(Sender: TObject);
begin
  n := aBlocks.Create; 
  n.NewBlock(self, Round(form1.Width/2-5), 50, 0,2);                       // Создаем 0й 
  n.aBlock[n.count-1].PopupMenu:=aBlocksPM; 
  n.NewBlock(self, Round(form1.Width/2-5), form1.Height-70, 1,2);    // и 1й блоки
  n.aBlock[n.count-1].PopupMenu:=aBlocksPM;
end;

procedure TForm1.FormMouseDown(Sender: TObject; Button: TMouseButton; Shift: TShiftState; X, Y: Integer);
begin
  n.NewBlock(self, x, y, n.count ,2); //Создаем новый блок при клике на форме
  n.aBlock[n.count-1].PopupMenu:=aBlocksPM; // Присваиваем ему контекстное меню
end;

procedure TForm1.PPBtn_DelBlckClick(Sender: TObject); // процедура выполняется при клике на Del в контекстном меню
var i:integer;
begin
if n.aBlockSelected<n.count-1 then 
  for i:= n.aBlockSelected to n.count-2 do // Сдвигаем все элементы массива по очереди
    begin
      n.aBlock[i]:=n.aBlock[i+1];
    end;
n.Count:=n.Count-1;
FreeAndNil(n.aBlock[n.Count]); // Обнуляем конечный элементт
SetLength(n.aBlock, n.Count); // Изменяем размер массива
end;
end.

unit Unit2;
interface
uses windows, SysUtils, System.Classes, Vcl.Graphics, Vcl.Controls, ExtCtrls;

type TImg = class(TImage)
  private
  public
   id,nu : integer; //id - тип блока, nu - его номер
  end;

 aBlocks = class
  private
    num : integer; // № конечного эл-та массива
  public
    aBlock: array of TImg;
    aBlockSelected:integer; // номер выделенного эл-та
    constructor Create;
    procedure NewBlock(Sender: TObject; X, Y, number, id1: Integer);
    destructor DeleteBlock(Sender: TObject;index: Integer);
    procedure Draw(numb:integer);
    procedure aBlockContextPopup(Sender: TObject; MousePos: TPoint; var Handled: Boolean);
    property Count: integer read num write num;
  end;

implementation

constructor aBlocks.Create;
begin
  num:=0; 
  aBlockSelected:=-1; // задаем начальные параметры
end;

procedure aBlocks.NewBlock(Sender: TObject; X, Y, number, id1: Integer);
begin
  if number=num then
  begin
    num := num + 1;
    SetLength(aBlock, num);
  end;
  aBlock[number] := TImg.Create(Sender as Tcomponent);
  with aBlock[number] do
  begin
    onContextPopup:=aBlockContextPopup;
    id:=id1;
    nu:=number;
    Left := X - 25;
    Top := Y - 25;
    Width := 50;
    Height := 50;
    Parent := Sender as TWinControl;
    Constraints.MinHeight:=40;
    Constraints.MinWidth:=40;
  end;
  if number>2 then aBlock[number].id:=id1 else aBlock[number].id:=2;
  Draw(number);
end;

destructor aBlocks.DeleteBlock(Sender: TObject; index: Integer);
 var i:integer;
begin
  //
end;

procedure aBlocks.Draw(numb:integer);
begin
  aBlock[numb].Canvas.Brush.Color:=clWhite;//Цвет Заливки
  aBlock[numb].Canvas.Pen.Width:=2;//толщина линии контура
  aBlock[numb].Canvas.Pen.Color:=clBlack;//Цвет контура линии
  aBlock[numb].Canvas.rectangle(1,1,aBlock[numb].Width,aBlock[numb].Height)
  case numb
if numb=0 then aBlock[numb].Canvas.TextOut(aBlock[numb].width-30,aBlock[numb].height-25,'n0')
       else if numb=1 then aBlock[numb].Canvas.TextOut(aBlock[numb].width-30,aBlock[numb].height-25,'nф')
             else aBlock[numb].Canvas.TextOut(aBlock[numb].width-30,aBlock[numb].height-30,inttostr(numb-1)+'N'); 
if numb=aBlockSelected then
  with aBlock[numb].Canvas do
     begin
      Brush.Color:=clBlack;
      rectangle(10,1,40,7);
     end;
end;

procedure aBlocks.aBlockContextPopup(Sender: TObject; MousePos: TPoint;
  var Handled: Boolean);
var i:integer; FirstSelect:boolean;
begin
  FirstSelect:=false;
  if aBlockSelected>-1 then
    begin
      i:=aBlockSelected;
      FirstSelect:=true;
    end;
  aBlockSelected:=(Sender as Timg).nu;
  Draw(aBlockSelected);
  if (aBlockSelected>-1) and FirstSelect then Draw(i);
  if (aBlock[aBlockSelected].nu=0) or (aBlock[aBlockSelected].nu=1)
    then aBlock[aBlockSelected].PopupMenu.Items[0].Enabled:=false
    else aBlock[aBlockSelected].PopupMenu.Items[0].Enabled:=true;
end;
end.
Поначалу блоки нормально удаляются, а потом начинает выдавать ошибки доступа. Подскажите в чем может быть проблема. Заранее спасибо!

Последний раз редактировалось Andr_XxX; 16.12.2012 в 19:36.
Andr_XxX вне форума Ответить с цитированием
Старый 16.12.2012, 19:24   #2
eoln
Старожил
 
Аватар для eoln
 
Регистрация: 26.04.2008
Сообщений: 2,645
По умолчанию

FreeAndNil(n.aBlock[n.Count]); освобождает память, но в этой памяти хранится лишь указатель на объект - на TImg, а сам объект нигде не удаляется.
То есть перед выше указанной командой надо сначало удалить объект, адрес которого там хранится.


И ещё
Код:
n.Count:=n.Count-1;
FreeAndNil(n.aBlock[n.Count]);
SetLength(n.aBlock, n.Count);
так делать неприлично, людей путаешь
eoln вне форума Ответить с цитированием
Старый 16.12.2012, 19:40   #3
Andr_XxX
Новичок
Джуниор
 
Регистрация: 16.12.2012
Сообщений: 2
По умолчанию

Цитата:
Сообщение от eoln Посмотреть сообщение
FreeAndNil(n.aBlock[n.Count]); освобождает память, но в этой памяти хранится лишь указатель на объект - на TImg, а сам объект нигде не удаляется.
То есть перед выше указанной командой надо сначало удалить объект, адрес которого там хранится.


И ещё
Код:
n.Count:=n.Count-1;
FreeAndNil(n.aBlock[n.Count]);
SetLength(n.aBlock, n.Count);
так делать неприлично, людей путаешь
Спасибо за ответ!
1) А как тогда удалить сам объект?
2) только дописал комменты =)
Andr_XxX вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Удаление элемента динамического массива mrCloud Общие вопросы Delphi 7 03.11.2012 12:31
замена элементов динамического массива ziman Общие вопросы C/C++ 1 17.12.2009 13:50
Удаление динамического массива Сергей089 Общие вопросы C/C++ 3 08.03.2009 13:13
Удаление элементов из динамического массива dashulka Общие вопросы Delphi 4 31.10.2008 14:03
Удаление элемента динамического массива Dogmat Помощь студентам 6 13.07.2008 14:33