Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2005.03.06;
Скачать: CL | DM;

Вниз

Как корректно уничтожить объект изнутри   Найти похожие ветки 

 
Zilog ©   (2005-02-16 17:14) [0]

Примерно такая ситуация.
Есть экземпляр класса, в котором есть помимо прочего есть и кнопка. В OnClick кнопки пытаюсь прописать уничтожение экземпляра класса... глючит.

Выглядит всё это примерно так:

type TMyClass = class
 But : TButton;
 
end;

procedure TMyClass.OnClick(...);
begin
 Free;

end;

Непонятно, как это реализовать?


 
Digitman ©   (2005-02-16 17:18) [1]


> В OnClick кнопки пытаюсь прописать уничтожение экземпляра
> класса... глючит


а ты не пытайся .. ибо - блажь


 
Zilog ©   (2005-02-16 17:22) [2]

т.е. объект можно удалить, только обращением не из самого объекта?


 
Alexander Panov ©   (2005-02-16 17:25) [3]

используй
class procedure
или
class procedure

Передавай параметром адрес экземпляра класса.


 
Zilog ©   (2005-02-16 17:45) [4]

если не сложно, не поясните ли как это сотворить?


 
Alexander Panov ©   (2005-02-16 18:04) [5]

 TTestClass=class
 private
   FList: TStringList;
 public
   constructor Create;
   destructor Destroy;override;

   class procedure Release(aObj: TTestClass);
   class function Delete(aObj: TTestClass): Integer;

   procedure Test;
 end;

procedure TForm1.Button1Click(Sender: TObject);
begin
 with TTestClass.Create do
 begin
   Test;
 end;
end;

{ TTestClass }

constructor TTestClass.Create;
begin
 Flist := TStringList.Create;
end;

class function TTestClass.Delete(aObj: TTestClass): Integer;
begin
 Result := 0;
 aObj.Free;
end;

destructor TTestClass.Destroy;
begin
 FList.Free;
 ShowMessage("Бобик сдох! Ёк");
 inherited;
end;

class procedure TTestClass.Release(aObj: TTestClass);
begin
 aObj.Free;
end;

procedure TTestClass.Test;
begin
 Release(Self);
end;


 
GuAV ©   (2005-02-16 18:16) [6]

Если наследник TForm - то Release.

Если контрол на форме - то слать форме WM_USER+N через PostMessage с контролом в качестве lParam или wParam, в обработчике WM_USER+N освобождать его.

Если фрейм - сделать что-то вроде release.


 
GuAV ©   (2005-02-16 18:17) [7]

Если после самоосвобождения нет попыток использовать поля класса, то можно просто free.


 
Набережных С. ©   (2005-02-16 18:22) [8]

>Zilog ©   (16.02.05 17:45) [4]

После возврата из обработчика события код, сгенерировавший это событие, может еще многократно к этому объету. Просто поставь точку останова в своем обработчике и посмотри в окне Call Stack на каком уровне вложенности находится твой код. И большая часть предшествующих методов - методы самого объета, имеющие полное право к нему обращаться как до вызова твоего обработчика, так и после. Уничтожать объект нужно извне. Например, можно из твоего обработчика послать посредством PostMessage специальное сообщение объету, в обработчике которого и вызвать деструктор - обработчики сообщений устроены так, что это безопасно. Для формы можно использовать ее метод Release, который так и поступает.
А вообще-то я подозреваю, что ты не на том пути. Чуть раньше свернул не в ту сторону:) Вернись немного назад и еще раз подумай.


 
Zilog ©   (2005-02-17 15:11) [9]

>>GuAV ©   (16.02.05 18:16) [6]
>>Если наследник TForm - то Release.
>>Если контрол на форме - то слать форме WM_USER+N через >>PostMessage с контролом в качестве lParam или wParam, в >>обработчике WM_USER+N освобождать его.

Решил сделать с помощью сообщений.
Сообщение у меня должен обрабатывать объект, так же созданный динамически (невизуальный, в то время как отправители сообщений - хоть и созданы динамически, но размещаются на форме).

Сделал так:

const StreamMsgID = WM_USER + 123;

type TMyClass = class

     procedure OnStreamMessage(var Msg : TMessage); message StreamMsgId;

end;

procedure TMyIRC.OnStreamMessage(var Msg: TMessage);
begin
 Beep;
end;

procedure TMyClass.OnObjKillClick(...);
begin
 PostMessage(FMain.Handle,StreamMsgID,0,0)

end

- не работает... :(


 
У   (2005-02-17 15:19) [10]

Zilog ©   (17.02.05 15:11) [9]
Сообщения, посланные с помощью PostMessage,
могут обрабатывать только объекты, являющиеся
виндовыми окнами.
К коим твой класс, как я понимаю, не относится.

Ты посылаешь сообщение форме
PostMessage(FMain.Handle,...
так и обработчик этого сообщения напиши у формы.
(в параметр его передай указатель на свой объект)


 
Zilog ©   (2005-02-17 15:37) [11]

>>У   (17.02.05 15:19) [10]

спасибо, ясно.

а можно ли как то ухитриться, и в своем объекте как то обработать сообщение?


 
У   (2005-02-17 15:42) [12]

Обработать можно, а вот послать, воспользовавшись
механизмом очереди сообщений (в чём цель) - нельзя.

Хотя в принципе можно, воспользоавшись окном-посредником.


 
Alx2 ©   (2005-02-17 16:08) [13]

Zilog ©   (17.02.05 15:37) [11]

Как вариант - завести киллера, который откуда-нибудь (например, из Application.OnIdle) будет вызываться и просматривать список подавших заявки на убийство.


 
Zilog ©   (2005-02-18 10:48) [14]

В итоге сделал так - посылаю сообщение форме, в качестве параметров указатели - объект к которому относится сообщение, и указатель собссно на объект (из массива, который относится к предыдущему объекту) который надо удалить.

ну и удаляю:  
 TMyObj(pointer(Msg.WParam)).DeleteStream(pointer(Msg.LParam));


 
Digitman ©   (2005-02-18 11:03) [15]


> Zilog ©   (18.02.05 10:48) [14]


а не проще ли сделать свой класс TMyClass наследником TWinControl ? чтобы не городить огород с передачей параметров-ссылок на объект ?

тогда все что тебе будет нужно - это послать сообщение StreamMsgID окну MyClass.Handle, диспетчеризацию же в общем случае автоматически выполнит цикл выборки/сообщений того потока, который создал объект твоего класса TMyClass (например, основной поток и цикл в методе Application.Run)


 
У   (2005-02-18 13:20) [16]

2Digitman ©   (18.02.05 11:03) [15]
Не слишком ли расточительно получится?
Всё-таки, окно - достаточно ценный ресурс.

В принципе, для решения задачи достаточно
одного окна-почтальона:
{-----------------------------------------------------}
unit Post2Obj;

interface

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

procedure PostMessageToObj(Obj: TObject; Msg: Cardinal; lParam, wParam: Longint);

implementation

const
 WM_POSTMESSAGE2OBJ = WM_USER + 133;

type
 TWMPostMessage2Obj = packed record
   Msg: Cardinal;
   Dest: TObject;
   ObjMsg: PMessage;
 end;

 TPostmanWin = class(TForm)
 public
   procedure WMPostMessage2Obj(var Message: TWMPostMessage2Obj); message WM_POSTMESSAGE2OBJ;
 end;

var
 thePostman: TPostmanWin;

procedure PostMessageToObj(Obj: TObject; Msg: Cardinal; lParam, wParam: Longint);
var objMsg: PMessage;
begin
 //Обычно для синглтонов делают так:
 //if thePostman = nil then
 //  thePostman := TPostmanWin.CreateNew(nil);
 // Но в этом случае окно может создаться не в главном потоке,
 // поэтому надёжнее создать его в initialization

 New(objMsg);
 objMsg^.Msg := Msg;
 objMsg^.lParam := lParam;
 objMsg^.wParam := wParam;
 PostMessage(thePostman.Handle, WM_POSTMESSAGE2OBJ,
   Longint(Obj), Longint(objMsg));
end;

procedure TPostmanWin.WMPostMessage2Obj(var Message: TWMPostMessage2Obj);
begin
 try
   Message.Dest.Dispatch(Message.ObjMsg^);
 finally
   Dispose(Message.ObjMsg);
 end;
end;

initialization
 thePostman := TPostmanWin.CreateNew(nil);
 thePostman.Hide;

finalization
 thePostman.Free;
end.


 
Erik1 ©   (2005-02-18 13:31) [17]

А по моему вобще форточек ненадо, Applicaton.Terminate и нет проблем. Или Halt еще добавить для уверености. А вобщето для таких целей можно любой поток использовать и послать ему можно много кого.



Страницы: 1 вся ветка

Текущий архив: 2005.03.06;
Скачать: CL | DM;

Наверх




Память: 0.51 MB
Время: 0.041 c
14-1108648630
Ilya___
2005-02-17 16:57
2005.03.06
подскажите, как можно щелчком на Label, открыть броузер с интерне


1-1109074067
syscoder
2005-02-22 15:07
2005.03.06
Компонент TStringGrid


8-1100782633
balcon
2004-11-18 15:57
2005.03.06
ширвание звука


14-1108455916
Hawk2
2005-02-15 11:25
2005.03.06
ТВ-Тюнеры


4-1106631182
SkierMax
2005-01-25 08:33
2005.03.06
Выключение компьютера под XP