Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2005.03.06;
Скачать: [xml.tar.bz2];

Вниз

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

 
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;
Скачать: [xml.tar.bz2];

Наверх




Память: 0.5 MB
Время: 0.032 c
6-1104171339
KarpUha
2004-12-27 21:15
2005.03.06
Ответ от модема


8-1100680884
BRemB
2004-11-17 11:41
2005.03.06
Формат файла TIF


4-1102524244
Костя
2004-12-08 19:44
2005.03.06
системное время


1-1108554718
AbramovVi
2005-02-16 14:51
2005.03.06
Классы из DLL


1-1108826118
DimonS
2005-02-19 18:15
2005.03.06
Подскажите пожалуйста как из реестра





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский