IceCold
IceCold

Reputation: 21134

How to free an object inside its event handler?

I have TMyClass, a class derived from TObject. It has a TTimer. Every few minutes, from Timer.OnTimer I check a web page. When the web page changes, I am done and I want to free MyClass. How do I free it?

My question is similar to this one BUT my 'control' is not a TControl. It is descendent of TObject. So, Messages won't work. Obviously, the solution will be to derive my class from TControl or higher. But let's say I don't want to do that. What would be the solution in this case?

Upvotes: 1

Views: 691

Answers (2)

ain
ain

Reputation: 22749

To receive messages you need to have window handle. You can allocate one using AllocateHWnd, something like

type
  TMyClass = class(TObject)
  private
    FHandle: HWND;
    procedure MyWndProc(var Msg: TMessage);
  public
    constructor Create; virtual;
    destructor Destroy; override;
  end;

constructor TMyClass.Create();
begin
  inherited Create();
  FHandle := AllocateHWnd(myWndProc);
end;

destructor TMyClass.Destroy;
begin
  DeallocateHWnd(FHandle);
  inherited;
end;

procedure TMyClass.MyWndProc(var Msg: TMessage);
begin
  case Msg.Msg of
    CM_RELEASE: begin
       Free;
    end;
    else Msg.Result := DefWindowProc(FHandle, Msg.Msg, Msg.WParam, Msg.LParam);
  end;
end;

Now you can post messages to the object using the FHandle as demonstrated in the post youre reffering to.

Upvotes: 5

Mason Wheeler
Mason Wheeler

Reputation: 84540

The basic idea behind using a message is correct: ensure that the object gets freed at a later point, after whatever code is currently calling it is finished.

A few years ago, I wrote a Delayed Action unit that gives you a simple way to accomplish this same effect without a TControl. You just call DelayExec and pass an anonymous method to it that will free the object, and it sets up a message internally that makes it happen once the message queue gets pumped.

Upvotes: 6

Related Questions