1

我尝试在 Lazarus (Free Pascal) 中使用以下代码获取主窗口句柄:

function FindMainWindow(Pid: LongWord): LongWord;
type
  TParam = record
    Window: HWnd;
    Test: Integer;
    Pid: LongWord;
  end;
  PParam = ^TParam;
var
  Params: TParam;
  function _FindMainWindow(Wnd: HWnd; MyLParam: PParam): Bool; stdcall;
  var
    WinPid: DWord;
  begin
    with MyLParam^ do
    begin
      Test := 2;
      GetWindowThreadProcessID(Wnd, @WinPid);
      Result := (WinPid <> Pid) or (not IsWindowVisible(Wnd))
        or (not IsWindowEnabled(Wnd));
      if not Result then begin
        Window := Wnd;
      end;
    end;
  end;
begin
  Params.Pid := Pid;
  Params.Test := 1;
  EnumWindows(@_FindMainWindow, LParam(@Params));
  ShowMessage('Done!');
  ShowMessage(IntToStr(Params.Test));
  Result := Params.Window;
end; 

问题是Params.Test运行回调后仍然为 1。我想修改函数Params中的_FindMainWindow

注意:我无法直接访问Params_FindMainWindow因为我收到“访问冲突”错误。

4

1 回答 1

3

当然在 Delphi 中,它也出现在 FPC 中,嵌套函数不能用作回调函数。使用 32 位编译器时,碰巧嵌套函数可以用作回调。但是这样的代码只被编译器接受,因为回调函数在 Windows 单元中被声明为无类型指针。如果 Windows 单元将它们声明为过程类型,您会发现编译器对象使用嵌套函数。

对于 64 位 Delphi 编译器,您根本不能将嵌套函数用作回调。虽然编译器允许您继续,但由于在 Windows 单元中使用了无类型指针(见上文),回调函数没有被正确调用。显然 FPC 也是如此。您将不得不停止对回调使用嵌套函数。

有趣的是,FPC 和 Delphi 编译器在这里都有相同的特性。我的猜测是 x64 调用约定是基于寄存器的约定,而不是基于堆栈的 x86stdcall是这个问题背后的驱动力。我敢打赌,如果您尝试使用嵌套的 x86register函数作为回调,那么在运行时也会失败。

于 2012-06-22T11:36:27.737 回答