Goover
Goover

Reputation: 410

EnumWindows in a nested class delphi

I've got some problems with EnumWindows function that uses callback function from a nested class:

TProcessWatch = class(TObject)
private
  ...
  type
    TProcessInfo = class(TObject)
    private
    type
      PEnumCallbackParam = ^TEnumCallbackParam;
      TEnumCallbackParam = class
        A : Integer;
        ...
      end;
    private
      FOwner : TProcessWatch;
      function FEnumWindowsCallback(hWindow : HWND; lParam : LPARAM) : BOOL; export;
      procedure SomeProc;
      ...
    end;
private
  FProcesses : TProcessInfo;
  ...
public
  ...

Within the SomeProc there is a call to EnumWindows

EnumCallbackParam := TEnumCallbackParam.Create;
try
  EnumCallbackParam.A := 0;
  EnumWindows(@TProcessWatch.TProcessInfo.FEnumWindowsCallback, LongInt(@EnumCallbackParam));
  ...
finally
  EnumCallbackParam.Free;
end;

And here is a FEnumWindowsCallback function listing:

function TProcessWatch.TProcessInfo.FEnumWindowsCallback(hWindow: HWND;
  lParam : LPARAM): BOOL; export;
var
  CallbackParam : PEnumCallbackParam;
begin
  CallbackParam := Pointer(lParam); // A is inaccessible
  Result := True;
  ...
end;

In runtime, when EnumWindows is called, FEnumWindowsCallback is always receiving hWindow = 0 and lParam is pointing to inaccessible value.

All this working fine if callback function is declared private in the form, but when I've tried to make this function private in nested class it went wrong.

Why? And how to make this working? The goal is to make FEnumWindowsCallback and all other involved functions private in TProcessWatch.

Upvotes: 2

Views: 226

Answers (1)

David Heffernan
David Heffernan

Reputation: 612794

The callback is declared wrongly. It should be:

class function EnumWindowsCallback(hWindow: HWND; 
  lParam: LPARAM): BOOL; static; stdcall; 

You were using the wrong calling convention, and an instance method.

Other comments:

  • EnumCallbackParam is already a pointer. You can pass it as the param.
  • Cast to LPARAM rather then LongInt so that you code will work if you ever compile to 64 bit.
  • The export keyword has no meaning in 32 or 64 bit Delphi. It is ignored and you should not use it since it adds clutter and may confuse.

Upvotes: 4

Related Questions