EnumWindows 在 64 位中表现异常 Delphi
EnumWindows behaving oddly in 64-bit Delphi
我在 Delphi XE3 中工作,在 64 位 Windows 8 机器上构建 32 位和 64 位应用程序。
我正在使用 EnumWindows 找出进程的主要 window 句柄 Windows 给定进程 ID。该代码在回调例程中使用 LPARAM 参数来传递指向记录的指针。
我使用的代码对于 32 位版本运行良好。
当我编译和 运行 64 位构建时失败。出现此问题是因为 LPARAM 值似乎是在 Wnd 参数中传递的。 Param 值始终设置为 $FFFF ...换句话说,我根本没有通过 HWND 值...所以它不是通过参数交换。
type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID : DWORD;
HWND : THandle;
end;
function EnumWindowsProc(Wnd: HWND; Param : LPARAM): Bool; stdcall;
var
PID : DWORD;
PEI : PEnumInfo;
begin
// in 32-bit Param matches the address of the param that is passed
// in 64-bit Param is set to $FFFF - however Wnd = the expected address
ShowMessage('PEI = '+IntToStr(Param));
PEI := PEnumInfo(Param);
GetWindowThreadProcessID(Wnd, @PID);
// the code fails at this next line in 64-bit build because PEI = $FFFF rather than the actual pointer passed
Result := (PID <> PEI^.ProcessID) or
(not IsWindowVisible(WND)) or
(not IsWindowEnabled(WND));
if not Result then PEI^.HWND := WND; //break on return FALSE
end;
function FindMainWindow(PID: DWORD): DWORD;
var
EI : TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
ShowMessage('PEI = '+IntToStr(LPARAM(@EI)));
EnumWindows(@EnumWindowsProc, LPARAM(@EI));
Result := EI.HWND;
end;
Win64 调用约定是否不同?还是我犯了其他一些根本性错误?
感谢接受任何帮助或想法。
你问题中的代码工作正常。您对 EnumWindowsProc
的声明是正确的。参数和 return 值具有正确的类型。调用约定是正确的,尽管这对于只有一个调用约定的 x64 Windows 实际上并不重要。
如果您使用问题中的代码构建一个简单的应用程序,您会发现它的行为正确并且枚举 windows 正确。
问题肯定是您的实际代码与您显示的代码不同。我的猜测是,在您的实际代码中,EnumWindowsProc
是一个嵌套函数:Why cannot take address to a nested local function in 64 bit Delphi? 但这只是一个猜测。我不知道你的真实代码是什么样的。我知道问题中的代码可以正常工作。
另一个评论是您错误地将 HWND
成员声明为 THandle
类型。这不会影响程序的正确性,但在语义上是错误的。我会这样声明该类型:
type
TEnumInfo = record
PID: DWORD;
Wnd: HWND;
end;
我在 Delphi XE3 中工作,在 64 位 Windows 8 机器上构建 32 位和 64 位应用程序。
我正在使用 EnumWindows 找出进程的主要 window 句柄 Windows 给定进程 ID。该代码在回调例程中使用 LPARAM 参数来传递指向记录的指针。
我使用的代码对于 32 位版本运行良好。
当我编译和 运行 64 位构建时失败。出现此问题是因为 LPARAM 值似乎是在 Wnd 参数中传递的。 Param 值始终设置为 $FFFF ...换句话说,我根本没有通过 HWND 值...所以它不是通过参数交换。
type
PEnumInfo = ^TEnumInfo;
TEnumInfo = record
ProcessID : DWORD;
HWND : THandle;
end;
function EnumWindowsProc(Wnd: HWND; Param : LPARAM): Bool; stdcall;
var
PID : DWORD;
PEI : PEnumInfo;
begin
// in 32-bit Param matches the address of the param that is passed
// in 64-bit Param is set to $FFFF - however Wnd = the expected address
ShowMessage('PEI = '+IntToStr(Param));
PEI := PEnumInfo(Param);
GetWindowThreadProcessID(Wnd, @PID);
// the code fails at this next line in 64-bit build because PEI = $FFFF rather than the actual pointer passed
Result := (PID <> PEI^.ProcessID) or
(not IsWindowVisible(WND)) or
(not IsWindowEnabled(WND));
if not Result then PEI^.HWND := WND; //break on return FALSE
end;
function FindMainWindow(PID: DWORD): DWORD;
var
EI : TEnumInfo;
begin
EI.ProcessID := PID;
EI.HWND := 0;
ShowMessage('PEI = '+IntToStr(LPARAM(@EI)));
EnumWindows(@EnumWindowsProc, LPARAM(@EI));
Result := EI.HWND;
end;
Win64 调用约定是否不同?还是我犯了其他一些根本性错误?
感谢接受任何帮助或想法。
你问题中的代码工作正常。您对 EnumWindowsProc
的声明是正确的。参数和 return 值具有正确的类型。调用约定是正确的,尽管这对于只有一个调用约定的 x64 Windows 实际上并不重要。
如果您使用问题中的代码构建一个简单的应用程序,您会发现它的行为正确并且枚举 windows 正确。
问题肯定是您的实际代码与您显示的代码不同。我的猜测是,在您的实际代码中,EnumWindowsProc
是一个嵌套函数:Why cannot take address to a nested local function in 64 bit Delphi? 但这只是一个猜测。我不知道你的真实代码是什么样的。我知道问题中的代码可以正常工作。
另一个评论是您错误地将 HWND
成员声明为 THandle
类型。这不会影响程序的正确性,但在语义上是错误的。我会这样声明该类型:
type
TEnumInfo = record
PID: DWORD;
Wnd: HWND;
end;