Page 1 of 1

MethodToProcedure not the same address when called

Posted: Mon Dec 05, 2011 11:05 pm
by runfastman
I am trying to use a class method in the SetTimer call. It seems to work (the procedure is called) however, it is not the same object. The address of "self" is not the same as the address passed into MethodToProcedure. Thus class variables I need access to are invalid.

Similar to - http://stackoverflow.com/questions/2787 ... s-api-call

Code: Select all

  TMyClass = class(TObject)
  private
    fTimer : Cardinal;
    SetTimerProc: Pointer;
    fMsg    : String;

    procedure TimerProc();

  public
    procedure DoIt();

    constructor Create(msg : String = 'Hello');
    destructor  Destroy(); override;
  end;

constructor TMyClass.Create(msg : String);
begin
  fMsg := msg;
end;

destructor TMyClass.Destroy;
begin
  KillTimer(0, fTimer);
  VirtualFree(SetTimerProc, 0, MEM_RELEASE);
  inherited;
end;

procedure TMyClass.DoIt;
begin
  SetTimerProc := SageRiskUtil.MethodToProcedure(Self, @TMyClass.TimerProc);
  fTimer := SetTimer(0, 0, 1, SetTimerProc);
  ShowMessage('Initial self Addr - ' + IntToStr(Integer(@Self)));
  KillTimer(0, fTimer);
end;

procedure TMyClass.TimerProc;
begin
  //ShowMessage(IntToStr(Integer(@Self)));
  ShowMessage(fMsg + ' TimerProc Self Addr -' + IntToStr(Integer(@Self)));
end;


///// Form Main////////

procedure TForm_Main.Button1Click(Sender: TObject);
var
  testClass : TMyClass;

begin
  testClass := TMyClass.Create();
  testClass.DoIt();
  testClass.Free;
end;

Re: MethodToProcedure not the same address when called

Posted: Tue Dec 06, 2011 9:21 am
by madshi
Your TimerProc() should be stdcall and match the parameter definitions required by SetTimer. See here:

http://msdn.microsoft.com/en-us/library ... 85%29.aspx

Re: MethodToProcedure not the same address when called

Posted: Tue Dec 06, 2011 3:01 pm
by runfastman
Thanks, works perfect. Haven't done many Windows_API calls.