MethodToProcedure 

www.madshi.net

Sometimes you need to pass a procedure address to a Windows API, but you would rather pass a method instead. In such a situation the function "MethodToProcedure" can come in handy. You enter a method address and your current "Self" value and you get a procedure address as the result, which you then can pass to a Windows API.

Please note that this works only for *stdcall* methods! Don't use it for any other calling convention! (But since almost all Windows APIs are stdcall, this should not be a big problem.)

After you don't need the procedure pointer anymore, please free it with "VirtualFree".

function MethodToProcedure (self       : TObject;
                            methodAddr : pointer) : pointer; overload;

function MethodToProcedure (method     : TMethod) : pointer; overload;

Here comes a little example which demonstrates a correct and useful usage of "MethodToProcedure":

unit EnumWindows;

// this unit implements a little class named TEnumWindows, which does nothing
// but enumerate all windows

interface

implementation

uses Windows, SysUtils, madTools;

type
  TEnumWindows = class
  private
    function EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
  public
    constructor Create;
  end;

constructor TEnumWindows.Create;
var EnumCallbackProc : pointer;
begin
  inherited;

  // you must pass a procedure address to EnumWindows
  // if you passed "@TWindowList.EnumCallbackMethod" your code would crash
  // because methods have an additional hidden "Self" parameter
  // so we need to convert our method to a procedure first
  EnumCallbackProc := MethodToProcedure(Self, @TEnumWindows.EnumCallbackMethod);

  // "EnumCallbackProc" now contains a pointer to a newly allocated procedure
  // which does nothing but jump to our "EnumCallbackMethod" with the correct parameters
  EnumWindows(EnumCallbackProc, 0);

  // don't forget to free the allocated procedure
  VirtualFree(EnumCallbackProc, 0, MEM_RELEASE);
end;

function TEnumWindows.EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
begin
  result := true;

  // do anything with the "window"s you get here...
  [...]
end;

end.