How to pass the address of a thread function as a callback to winapi?

戏子无情 提交于 2019-12-30 12:47:09

问题


I have a simple thread and inside the execute I try to call EnumWindows() with the address of one of the functions defined in the thread. So I'm trying to do this: EnumWindows(@cbEnumWindowsClickOK, 0); where cbEnumWindowsClickOK is an EnumWindowProc defined inside the thread class, like so:

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

When I try this I keep getting "Error: Variable required", hinting that it doesn't interpret @cbEnumWindowsClickOK as an address. If I move the function to a global scope (removing it from the thread) it does work.

Any thoughts on how I can fix this?


回答1:


You have to pass EnumWindows a plain old function, i.e. one that is not bound to an instance. You must pass the instance in separately. Like this:

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;

The reason it must be done this way is that an instance method does not match the required signature for EnumWindows. An instance method has an extra, implicit, parameter containing the instance reference, i.e. Self. This is how you are able to refer to instance members. But the signature for EnumFunc does not cater for this.



来源:https://stackoverflow.com/questions/7706637/how-to-pass-the-address-of-a-thread-function-as-a-callback-to-winapi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!