EnumWindows 有时不工作
EnumWindows not working sometimes
我正在创建一个函数来获取所有 window 个具有 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()
的结果设置为任何值,因此当 EnumWindowsProcMy()
退出时它包含一个随机值。您必须 return 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.
我正在创建一个函数来获取所有 window 个具有 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()
的结果设置为任何值,因此当 EnumWindowsProcMy()
退出时它包含一个随机值。您必须 return 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.