1

In c++ one can do it this way:

HWND g_HWND=NULL;
BOOL CALLBACK EnumWindowsProcMy(HWND hwnd,LPARAM lParam)
{
    DWORD lpdwProcessId;
    GetWindowThreadProcessId(hwnd,&lpdwProcessId);
    if(lpdwProcessId==lParam)
    {
        g_HWND=hwnd;
        return FALSE;
    }
    return TRUE;
}

EnumWindowsProcMy,m_ProcessId);

(link)

The Delphi translation would be:

function GetWindowHandle(ProcessId: Cardinal): THandle;
var
  hFound: THandle;

function EnumWindowsProcMy(_hwnd: HWND; ProcessId: Cardinal): BOOL; stdcall;
var
  dwPid: Cardinal;
begin
  GetWindowThreadProcessId(_hwnd, @dwPid);

  if ProcessId = dwPid then
  begin
    hFound := _hwnd;
    Result := False;
  end
  else
    Result := True;
end;

begin
  EnumWindows(@EnumWindowsProcMy, LPARAM(ProcessId));
  Result := hFound;
end;

However it seems the "embedded" function can't acces the variable hFound correctly.

If i declare the variable outside of the function (global variable) it works fine. But that's bad by design.

One way to get around this would be to e.g. pass a record to EnumWindowProcMy and save the desired Handle there.

However i am wondering why the code doesn't work as i think i translated it correctly.

Community
  • 1
  • 1
ChrisB
  • 2,497
  • 2
  • 24
  • 43

1 Answers1

4

Don't use an "embedded" function. Use a standalone function just like your C++ code did.

Nested functions cannot be passed as pointers. A good rule of thumb is that if you have to use the @ operator to get the compiler to allow you to pass a function pointer, then it's probably wrong. Always try using function pointers without the @ operator first. The compiler might detect errors that way.

If you don't want to use a global variable, but you need to pass more than one unit of information to a callback function, then you need to use a record. The C++ code doesn't use a record because it uses a global variable instead. That's where your translation deviated from the original.

Rob Kennedy
  • 161,384
  • 21
  • 275
  • 467