我尝试使用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
,因为我收到了“访问冲突”错误。
答案 0 :(得分:3)
当然在Delphi中,它看起来也是FPC,嵌套函数无法用作回调函数。使用32位编译器时,嵌套函数可以用作回调。但是这样的代码只能被编译器接受,因为回调函数在Windows单元中被声明为无类型指针。如果Windows单元将它们声明为过程类型,则会发现编译器对象使用嵌套函数。
对于64位Delphi编译器,根本不能使用嵌套函数作为回调。虽然编译器允许您继续使用,但由于在Windows单元中使用了无类型指针(参见上文),因此未正确调用回调函数。显然,FPC也是如此。您将不得不停止使用嵌套函数进行回调。
有趣的是,FPC和Delphi编译器在这里具有相同的特性。我的猜测是x64调用约定,这是一个基于寄存器的约定,而不是基于堆栈的x86 stdcall
是这个问题的驱动力。我敢打赌,如果你试图使用嵌套的x86 register
函数作为回调,那么在运行时也会失败。