Форум: "Основная";
Текущий архив: 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