【问题标题】:EnumWindows behaving oddly in 64-bit DelphiEnumWindows 在 64 位 Delphi 中表现异常
【发布时间】:2015-08-14 23:11:13
【问题描述】:

我正在使用 Delphi XE3,在 64 位 Windows 8 机器上构建 32 位和 64 位应用程序。

我正在使用 EnumWindows 来找出给定进程 ID 的进程主窗口的 Windows 句柄。该代码使用回调例程中的 LPARAM 参数来传递指向记录的指针。

我使用的代码在 32 位版本中运行良好。

当我编译和运行 64 位版本时它失败了。出现此问题的原因似乎是在 Wnd 参数中传递 LPARAM 值。 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 调用约定是否不同?还是我犯了其他根本性的错误?

感激地接受任何帮助或想法。

【问题讨论】:

  • 能否展示一个完整的程序
  • 您是要查找 32 位还是 64 位应用程序的主窗口?如果我没记错的话,即使在检索基本进程信息时,您也需要为 32 位和 64 位进程分别编写代码。
  • @Silver 不,所有窗口都被枚举

标签: delphi winapi delphi-xe3 win64


【解决方案1】:

您问题中的代码运行良好。您对EnumWindowsProc 的声明是正确的。参数和返回值具有正确的类型。调用约定是正确的,尽管这对于只有一个调用约定的 x64 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;

【讨论】:

  • 确实,它必须是“嵌套函数”的情况,因为代码在 x64 上运行良好
  • 水晶球调试!
  • @LeonardoHerrera 好吧,我无法得到与提问者报告相同的行为,但我怀疑他们的代码可能对我们拥有的代码进行了其他更改。尽管如此,我相信问题中的代码有效,这是主要的。
  • David - 谢谢 .. 就是这样,我将回调函数 (EnumWindowsProc) 作为另一个函数中的嵌套例程。将其移出成为独立函数会在 32 位和 64 位应用程序中产生相同(正确)的操作。
  • 我猜对了,嗯?! FWIW,逐字发布代码是值得的,这样您就不必依赖我们的猜测技巧。最后,您可能愿意接受这个答案。谢谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-07-22
  • 2014-12-11
  • 1970-01-01
  • 2022-01-23
相关资源
最近更新 更多