gpt4 book ai didi

arrays - 动态数组可以用作 Windows 回调函数的参数吗?

转载 作者:可可西里 更新时间:2023-11-01 11:11:41 24 4
gpt4 key购买 nike

我正在重做一些代码以准备好 64 位。这使用带有回调的 EnumWindows 来返回列表运行 delphi 应用程序(除了 IDE 和它本身)然后被杀死。起初它使用 TStringlist 来保存这些应用程序的句柄。我想更改它以直接以数字形式收集句柄。我使用通用 TList 收集句柄,得出了一个非常令人满意的解决方案,如下所示。

在此过程中,我最初尝试使用动态数组 - 它没有用。验证了TList的解法后,出于学术兴趣,重温了一下,尝试了各种方法来使用动态数组来实现它——但都没有成功。我在文档中找不到任何禁令,尽管我确实遇到过Rudy V 博客中的这条注释:“无论如何,Delphi 字符串和动态数组不应作为引用计数类型传递给 API 函数……”

所以,我只是在寻求一个“裁决”,即动态数组可以或不能用作回调函数的参数。

type
THandleList=Tlist<THandle>;
const
ReqdClass: string = 'TApplication' ;


procedure KillWindowViaHandle(Ahwnd:THandle; Amsg: Cardinal=WM_CLOSE);
begin
PostMessage(Ahwnd, Amsg, 0, 0);
end;

// Get Active "User" Applications (except for bds.exe & caller). Relies on top
// level window having classname of TApplication. Returns list of handles.

function FindActiveUSERApps(AHandle: HWND; AList: lparam): BOOL ; stdcall;
var
classname: string;
pid: DWORD;
imagename: string;
begin
Result := true; // keep it going .. want them all
GetWindowThreadProcessID(AHandle, @pid); // not interested in ThreadID returned
imagename := GetProcessFileName(pid) ;
SetLength(ClassName, 255);
SetLength(ClassName, GetClassName(AHandle, PChar(className), Length(className)));
if ( ansicontainstext(classname, ReqdClass) ) and
( not ansisametext(ImageName, 'bds.exe')) and
( not ansisametext(ImageName, ExtractFileName(Application.ExeName))) then
THandleList(Alist).Add(AHandle) ;
end;


function GetActiveUSERApps(AList: THandleList): boolean;
begin
AList.Clear;
EnumWindows(@FindActiveUSERApps, lparam(AList) );
result := Alist.Count > 0;
end;


function KillActiveUSERApps: boolean;
var
i : integer;
ActiveList: THandleList;
begin
result := false;
ActiveList := THandleList.Create;
try
GetActiveUSERApps(ActiveList);
for i:= 0 to activelist.Count - 1 do
KillWindowviaHandle( ActiveList[i] );

// noticed that some processes were resistant to being killed via WM_CLOSE.
// So try gentle approach first, and then if necessary, use the big stick.
GetActiveUSERApps(activeList);
for i:= 0 to activelist.Count - 1 do
KillWindowviaHandle( ActiveList[i], WM_QUIT );

result := true;
finally
ActiveList.Free;
end;
end;

最佳答案

在没有实际看到您使用动态数组的实现的情况下,我假设您通过使用 SetLength 扩展它来向该数组添加元素。这反过来又改变了内部是指针的数组变量。因此,调用方法仍然使用指向它作为参数传递的不存在的动态数组的旧指针变量。

您可以通过使用指向动态数组的指针来解决这个问题。

type
THandleList = TArray<THandle>;
PHandleList = ^THandleList;

function FindActiveUSERApps(AHandle: HWND; AList: lparam): BOOL ; stdcall;
var
...
PList: PHandleList;
begin
...
PList := PHandleList(AList);
SetLength(PList^, Length(PList^) + 1);
PList^[High(PList^)] := AHandle;
end;


function GetActiveUSERApps(var AList: THandleList): boolean;
begin
AList.Clear;
EnumWindows(@FindActiveUSERApps, lparam(@AList) );
result := Alist.Count > 0;
end;

也就是说,我个人更喜欢 TList 方法,因为它简单明了。特别是因为您可以使用 AList.ToArray 轻松地从中返回一个动态数组。

关于arrays - 动态数组可以用作 Windows 回调函数的参数吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42320531/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com