【问题标题】:EnumWindows not working sometimesEnumWindows 有时不工作
【发布时间】:2017-10-12 01:09:55
【问题描述】:

我正在创建一个函数来获取所有带有 processid 的窗口句柄。

我的代码:

unit untCommonUitls;

interface

uses
   System.SysUtils, Winapi.Windows, Winapi.Messages, System.Classes;



function GetWindowHandlesByPID(const cPID: Cardinal): TStringList;

var
  slHandles: TStringList;

implementation

function GetWindowHandlesByPID(const cPID: Cardinal): TStringList;
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;
      slHandles.Add(IntToStr(hFound));
    end;
  end;

begin
  if not Assigned(slHandles) then
  begin
    slHandles := TStringList.Create;
  end;
  slHandles.Clear;
  EnumWindows(@EnumWindowsProcMy, LPARAM(cPID));
  Result := slHandles;
end;

当我尝试这段代码时,一切正常,EnumWindowsProcMy 多次调用,slHandles 获取句柄列表;

但在其他情况下,它不起作用。 EnumWindowsProcMy 只调用一次,所以slHandles 为空。

【问题讨论】:

  • 从您的EnumWindowsProcMy 返回值(Result := True;,如果您想枚举所有窗口)。我不知道它背后是什么,但你错过了它。而且我不会为该回调使用嵌套函数。
  • @Victoria 谢谢。缺少返回值是我的错。
  • 编译器警告错误。不要忽视警告和提示。

标签: delphi winapi window-handles


【解决方案1】:

您没有将EnumWindowsProcMy() 的结果设置为任何值,因此当EnumWindowsProcMy() 退出时它包含一个随机值。您必须返回 TRUE 以继续枚举或返回 FALSE 以停止枚举。

但是,更重要的是,您不能EnumWindows() 回调(或任何其他Win32 回调,就此而言)使用嵌套函数!嵌套函数共享父函数的堆栈帧,因此它们可以相互共享参数和局部变量。因此,这涉及编译器技巧,使嵌套函数与 Win32 API 不兼容。回调必须是独立函数!

改用类似的东西:

unit untCommonUitls;

interface

uses
   System.Classes;

function GetWindowHandlesByPID(const cPID: Cardinal): TStringList;

implementation

uses
  Winapi.Windows;

var
  slHandles: TStringList = nil;

function MyEnumWindowsProc(wnd: HWND; ProcessId: LPARAM): BOOL; stdcall;
var
  dwPid: Cardinal;
begin
  GetWindowThreadProcessId(wnd, @dwPid);
  if dwPid = ProcessId then
    slHandles.Add(IntToStr(wnd));
  Result := TRUE;
end;

function GetWindowHandlesByPID(const cPID: Cardinal): TStringList;
begin
  if not Assigned(slHandles) then
    slHandles := TStringList.Create
  else
    slHandles.Clear;
  EnumWindows(@MyEnumWindowsProc, cPID);
  Result := slHandles;
end;

finalization
  slHandles.Free;

end.

或者:

unit untCommonUitls;

interface

uses
   System.Classes;

procedure GetWindowHandlesByPID(const cPID: Cardinal; List: TStrings);

implementation

uses
  Winapi.Windows;

type
  PMyEnumInfo = ^MyEnumInfo;
  MyEnumInfo = record
    ProcessId: DWORD;
    List: TStrings;
  end;

function MyEnumWindowsProc(wnd: HWND; param: LPARAM): BOOL; stdcall;
var
  dwPid: Cardinal;
begin
  GetWindowThreadProcessId(wnd, @dwPid);
  if dwPid = PMyEnumInfo(param).ProcessId then
    PMyEnumInfo(param).List.Add(IntToStr(wnd));
  Result := TRUE;
end;

procedure GetWindowHandlesByPID(const cPID: Cardinal; List: TStrings);
var
  Info: MyEnumInfo;
begin
  Info.ProcessId := cPID;
  Info.List := List;
  List.BeginUpdate;
  try
    EnumWindows(@MyEnumWindowsProc, LPARAM(@Info));
  finally
    List.EndUpdate;
  end;
end;

end.

【讨论】:

    猜你喜欢
    • 2017-01-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多