Rambler's Top100
"Knowledge itself is power"
F.Bacon
Поиск | Карта сайта | Помощь | О проекте | ТТХ  
 Круглый стол
  
Правила КС
>> Настройки

Фильтр вопросов
>> Новые вопросы
отслеживать по
>> Новые ответы

Избранное

Страница вопросов
Поиск по КС


Специальные проекты:
>> К л ю к в а
>> Г о л о в о л о м к и

Вопрос №

Задать вопрос
Off-topic вопросы

Помощь

 
 К н и г и
 
Книжная полка
 
 
Библиотека
 
  
  
 


Поиск
 
Поиск по КС
Поиск в статьях
Яndex© + Google©
Поиск книг

 
  
Тематический каталог
Все манускрипты

 
  
Карта VCL
ОШИБКИ
Сообщения системы

 
Форумы
 
Круглый стол
Новые вопросы

 
  
Базарная площадь
Городская площадь

 
   
С Л С

 
Летопись
 
Королевские Хроники
Рыцарский Зал
Глас народа!

 
  
ТТХ
Конкурсы
Королевская клюква

 
Разделы
 
Hello, World!
Лицей

Квинтана

 
  
Сокровищница
Подземелье Магов
Подводные камни
Свитки

 
  
Школа ОБЕРОНА

 
  
Арсенальная башня
Фолианты
Полигон

 
  
Книга Песка
Дальние земли

 
  
АРХИВЫ

 
 

Сейчас на сайте присутствуют:
 
 
 06:57 inferno
 
 
Во Флориде и в Королевстве сейчас  07:07[Войти] | [Зарегистрироваться]
Ответ на вопрос № 46005

19-10-2006 04:22
D7/чайник



Доброго времени суток славным жителям!
Вопрос по созданию и освобождению объектов, созданных в RunTime.

Начитался я Е.Филлиповой и решил сам попробовать. Суть проста: по нажатию на кнопку "+" ниже нее создается панелька с кнопками "+" и "-", в которой по нажатию на кнопку "+" повторяется точно такая же ситуация. А вот по нажатию на кнопку "-" "родительская" панелька должна уничтожаться вместе с сендером (т.е. с кнопкой "-" и рядом лежащей кнопкой "+"). Вот тут и проблема.


interface
....
var  No:Integer;

implementation
...
procedure TForm1.CreateNewPanel(Sender: TObject);
var MyPnl: array [0..4] of TPanel;
    BtnPlus,BtnMinus: array [0..4] of TButton;
begin
if not(No > High(MyPnl)) then
  begin
    MyPnl[No]:= TPanel.Create(Form1);//создаем панель
    with MyPnl[No] do//назначаем ей
      begin
      Height:= 30;//высоту
      Name:= ClassName + IntToStr(No);//имя
      Top:= Panel6.Top + Height;//верхнюю координату
      Align:= alTop;//выравнивание
      Parent:= Form1;//родителя
      Tag:= No;
      end;{with}

    //создаем дочерние контролы
    {TButton}
    BtnPlus[No]:= TButton.Create(MyPnl[No]);
    with BtnPlus[No] do
      begin
      {тут  c OnClick разобрался}
      end;

    BtnMinus[No]:= TButton.Create(MyPnl[No]);
    with BtnMinus[No] do
      begin
      BoundsRect:= Bounds(Parent.Width - 20,5,17,17);
      Anchors:= Anchors + [akTop,akRight] - [akLeft,akBottom];
      Name:= 'BtnMinus' + IntToStr(No);
      Caption:= '-';
      Parent:= MyPnl[No];
      Tag:= No;
      OnClick:= BtnMinusClick;
      end;

    Form1.Height:= Form1.Height + MyPnl[No].Height;//увеличиваем высоту формы
    Form1.Refresh;//перерисовываем форму
    Inc(No); //No:= No+1;//увеличиваем номер в массиве
  end;{if..not(i > High(MyPnl))..then}
end;

procedure TForm1.BtnMinusClick(Sender: TObject);
begin
{пытаемся удалить панель, на которой находится сендер}
TButton(Sender).Parent.Free;//вываливается AV
end;


Насколько я понимаю, если б сендер уничтожал не самого себя а соседнюю панель, то все было бы тип-топ.

Был бы весьма признателен гуру за подсказки и возможные комментарии.

[+] Добавить в избранные вопросы

Отслеживать ответы на этот вопрос по RSS

Ответы:


Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице.
Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.

20-10-2006 23:49 | Сообщение от автора вопроса
Оффтоп

>>> вы не заметили? Юрий его зовут.
Жаль, что нет возможности редактировать свои посты. Ссылку я заметил потом (картинки у меня отключены, поэтому правый край страницы "уезжает" за пределы экрана, приходится скролить вправо). А ввобще, приятно, что модератор форума так чутко реагирует на общение - значит, все тут в порядке с порядком (каламбур). Буду заглядывать сюда в первую очередь ))

20-10-2006 05:58 | Замечание модератора
огромнейший респект, особенно Ins (жаль, не знаю имени)

А то, что подпись - это гиперссылка, которая открывает страницу с более подробной информацией о человеке, вы не заметили? Юрий его зовут.

19-10-2006 15:55 | Сообщение от автора вопроса
To Ins и  DRON

огромнейший респект, особенно Ins (жаль, не знаю имени) за терпение и конструктивизм. Все получилось просто и изящно. Поскольку этого ребуют правила, привожу код того, что у меня получилось (и заработало).


{добавлено в раздел interface - остальной код в первом посте}
interface

uses ...
 
type

  TPanel =class(ExtCtrls.TPanel)
  private
    procedure CMRelease(var Message: TMessage); message CM_RELEASE;
  end;

  TForm1 = class(TForm) ...

implementation
...

{$R *.dfm}

procedure TForm1.MyBtnMinusClick(Sender: TObject);
begin
No:= TButton(Sender).Tag - 1;
if No > Low(MyBtnMinus)//если сендер - кнопка не из первой панели (MyPnl[0])
  then
    begin//фокус на собратьев любой из массива панелей MyPnl
      MyBtnPlus[No-1].Enabled:= True;
      MyBtnMinus[No-1].Enabled:= True;
      MyBtnMinus[No-1].SetFocus;
    end
  else//иначе выше лежит "постоянная" панель, созданный в OnCreate формы
    begin
      BtnPlus.Enabled:= True;
      BtnPlus.SetFocus;//фокус на "постоянную" кнопку
    end;

Form1.Height:= Form1.Height - MyPnl[No].Height;//уменьшаем высоту формы
Form1.Refresh;//перерисовываем форму

//уничтожаем сендер "чужими" руками
PostMessage(TButton(Sender).Parent.Handle,CM_RELEASE,0,0);
end;

procedure TPanel.CMRelease(var Message: TMessage);
begin
Free;
end;



Еще раз, большое спасибо.

19-10-2006 07:31
Можно ещё вот сюда заглянуть:
http://www.delphikingdom.com/asp/answer.asp?IDAnswer=40427

19-10-2006 05:44
Почему так происходит, что из обработчика OnClick нельзя уничтожить объект, вызвавший это событие?
Что происходит, когда пользователь отпускает левую кнопку мыши над кнопкой:
1. Вызывается метод WMLButtonUp класса TControl.

procedure TControl.WMLButtonUp(var Message: TWMLButtonUp);
begin
  inherited;
  if csCaptureMouse in ControlStyle then MouseCapture := False;
  if csClicked in ControlState then
  begin
    Exclude(FControlState, csClicked);
    if PtInRect(ClientRect, SmallPointToPoint(Message.Pos)) then Click;
  end;
  DoMouseUp(Message, mbLeft);
end;


2. Как видно, из этого метода вызывается метод Click.

procedure TControl.Click;
begin
  { Call OnClick if assigned and not equal to associated action's OnExecute.
    If associated action's OnExecute assigned then call it, otherwise, call
    OnClick. }

  if Assigned(FOnClick) and (Action <> nil) and (@FOnClick <> @Action.OnExecute) then
    FOnClick(Self)
  else if not (csDesigning in ComponentState) and (ActionLink <> nil) then
    ActionLink.Execute(Self)
  else if Assigned(FOnClick) then
    FOnClick(Self);
end;


3. То есть из этого метода происходит вызов определенного вами обработчика события OnClick.
4. В методе OnClick вы уничтожаете экземпляр класса.
5. После возврата из обработчика события, управление возвращается в метод Click, а так как там больше никаких действий производить не нужно - тут же в метод WMLButtonUp.
6. Далее должна выполниться строчка

DoMouseUp(Message, mbLeft);


или другими словами

self.DoMouseUp(Message, mbLeft);


Но ведь экземпляр self уже уничтожен!

Приведенный ниже способ заставляет объект уничтожиться после того, как будет полностью обработано сообщение мыши.

19-10-2006 05:11
Вот один из способов самоубийства объектов (по аналогии с методом форм Release). Кидаем на форму панель, на нее - кнопку. По нажатии на кнопку, панель с кнопкой уничтожиться.

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls, ExtCtrls;

type
  TPanel =class(ExtCtrls.TPanel)
  private
    procedure CMRelease(var Message: TMessage); message CM_RELEASE;
  end;

  TForm1 = class(TForm)
    Panel1: TPanel;
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

procedure TForm1.Button1Click(Sender: TObject);
begin
  PostMessage(TButton(Sender).Parent.Handle,CM_RELEASE,0,0);
end;

{ TPanel }

procedure TPanel.CMRelease(var Message: TMessage);
begin
  Free;
end;

end.


Добавьте свое cообщение

Вашe имя:  [Войти]
Ваш адрес (e-mail):На Королевстве все адреса защищаются от спам-роботов
контрольный вопрос:
Два кольца, два конца, посередине гвоздик.
в качестве ответа на вопрос или загадку следует давать только одно слово в именительном падеже и именно в такой форме, как оно используется в оригинале.
Надоело отвечать на странные вопросы? Зарегистрируйтесь на сайте.
Тип сообщения:
Текст:
Жирный шрифт  Наклонный шрифт  Подчеркнутый шрифт  Выравнивание по центру  Список  Заголовок  Разделительная линия  Код  Маленький шрифт  Крупный шрифт  Цитирование блока текста  Строчное цитирование
  • вопрос Круглого стола № XXX

  • вопрос № YYY в тесте № XXX Рыцарской Квинтаны

  • сообщение № YYY в теме № XXX Базарной площади
  • обсуждение темы № YYY Базарной площади
  •  
     Правила оформления сообщений на Королевстве

    Страница избранных вопросов Круглого стола.
      
    Время на сайте: GMT минус 5 часов

    Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter.
    Функция может не работать в некоторых версиях броузеров.

    Web hosting for this web site provided by DotNetPark (ASP.NET, SharePoint, MS SQL hosting)  
    Software for IIS, Hyper-V, MS SQL. Tools for Windows server administrators. Server migration utilities  

     
    © При использовании любых материалов «Королевства Delphi» необходимо указывать источник информации. Перепечатка авторских статей возможна только при согласии всех авторов и администрации сайта.
    Все используемые на сайте торговые марки являются собственностью их производителей.

    Яндекс цитирования