如何将线程函数的地址作为回调传递给winapi?

Ran*_*Ran 1 delphi winapi multithreading pointers

我有一个简单的线程,在执行中我尝试使用线程中定义的函数之一的地址调用EnumWindows().所以我想这样做:EnumWindows(@cbEnumWindowsClickOK,0); 其中cbEnumWindowsClickOK是在线程类中定义的EnumWindowProc,如下所示:

TAutoClickOKThread = class(TThread)
private
     fExitEvent : THandle;
     function cbEnumWindowsClickOK(Wnd: HWND; Info: Pointer): BOOL;
public
   constructor Create(ExitEvent : Thandle);
   procedure Execute(); override;
end;
Run Code Online (Sandbox Code Playgroud)

当我尝试这个时,我不断收到"错误:需要变量",暗示它不会将@cbEnumWindowsClickOK解释为地址.如果我将函数移动到全局范围(从线程中删除它)它确实有效.

有关如何解决此问题的任何想法?

Dav*_*nan 6

您必须传递EnumWindows一个普通的旧函数,即一个未绑定到实例的函数.您必须单独传递实例.像这样:

function EnumFunc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
begin
  Result := TAutoClickOKThread(lParam).cbEnumWindowsClickOK(hwnd);
  //note that there is now no need for the Info parameter
end;
...
procedure TAutoClickOKThread.Execute;
begin
  ...
  EnumWindows(EnumFunc, LPARAM(Self));
  ...
end;
Run Code Online (Sandbox Code Playgroud)

必须以这种方式完成的原因是实例方法与所需的签名不匹配EnumWindows.实例方法具有包含实例引用的额外的隐式参数,即Self.这是您能够引用实例成员的方式.但签名EnumFunc并不适合这一点.