Delphi指针、数组、句柄
我不能使用自定义记录来处理指针,然后创建记录数组,然后再创建指向该记录的指针,具体来说,我想要实现的是为每个顶级窗口句柄创建一个具有给定类名的记录,这意味着每个窗口都有1个以上的句柄,我使用EnumChildWindow来获取具有in的子窗口的句柄。我想把这些记录下来,并将其传递给一个带有标题的组合框,使记录成为该项目的一个对象,这样我以后可以通过选择它来访问每个记录 我的问题是我对指针的处理,在第一次向一个数组记录添加任何数据时,我总是被拒绝访问 在这里休息Delphi指针、数组、句柄,delphi,pointers,enums,delphi-xe4,window-handles,Delphi,Pointers,Enums,Delphi Xe4,Window Handles,我不能使用自定义记录来处理指针,然后创建记录数组,然后再创建指向该记录的指针,具体来说,我想要实现的是为每个顶级窗口句柄创建一个具有给定类名的记录,这意味着每个窗口都有1个以上的句柄,我使用EnumChildWindow来获取具有in的子窗口的句柄。我想把这些记录下来,并将其传递给一个带有标题的组合框,使记录成为该项目的一个对象,这样我以后可以通过选择它来访问每个记录 我的问题是我对指针的处理,在第一次向一个数组记录添加任何数据时,我总是被拒绝访问 在这里休息 Param[Form1.iEnum
Param[Form1.iEnumWin].MainHwnd:= aHwnd;
这是我正在使用的完整代码,这样人们可以更好地理解我正在尝试做什么
implementation
{$R *.dfm}
type
TMyEnumParam = record
sTitle: String;
MainHwnd: Hwnd;
InTxtHwnd: Hwnd;
OutTxtHwnd: Hwnd;
NickListHwnd: Hwnd;
end;
PMyEnumParam = ^TMyEnumParam;
type
ATMyEnumParam = Array[0..9] of PMyEnumParam;
PATMyEnumParam = ^ATMyEnumParam;
{ Get the window Title based on Hwnd }
function GetWindowTitle(HWND: HWND): string;
begin
SetLength(Result, 255);
SetLength(Result, GetWindowText(HWND, PChar(Result), 255));
end;
{ Get the Classname based on Hwnd }
function GetWindowClass(HWND: HWND): string;
begin
SetLength(Result, 255);
SetLength(Result, GetClassName(HWND, PChar(Result), 255));
end;
{ EnumChildWidows Callback Add to our records }
Function EnumChildProc(aHwnd: Hwnd; Param: PMyEnumParam): Boolean; stdcall;
begin
if ((GetDlgCtrlID(aHwnd) = 202) and (isWindowVisible(aHwnd) = True)) then
Param.InTxtHwnd:= aHwnd;
if ((GetDlgCtrlID(aHwnd) = 203) and (isWindowVisible(aHwnd) = True)) then
Param.OutTxtHwnd:= aHwnd;
if ((GetDlgCtrlID(aHwnd) = 1789) and (isWindowVisible(aHwnd) = True)) then
Param.NickListHwnd:= aHwnd;
Result:= True;
end;
{ EnumWindow fill our array of records for each window }
function EnumWindowsProc(aHwnd: HWND; Param: PATMyEnumParam): BOOL; stdcall;
begin
Result := True;
if GetWindowClass(aHwnd) = 'DlgGroupChat Window Class' then
begin
Param[Form1.iEnumWin].MainHwnd:= aHwnd;
Param[Form1.iEnumWin].sTitle:= GetWindowTitle(aHwnd);
EnumChildWindows(aHwnd, @EnumChildProc, LParam(@Param[Form1.iEnumWin]));
Form1.cbbRooms.AddItem(Param[Form1.iEnumWin].sTitle, TObject(Param[form1.iEnumWin]));
inc(Form1.iEnumWin);
end;
end;
{ On change display room Title for each item }
procedure TForm1.cbbRoomsChange(Sender: TObject);
var
i: Integer;
aHwnd: PMyEnumParam;
begin
i := cbbRooms.ItemIndex;
if cbbRooms.ItemIndex <> -1 then
begin
aHwnd:= PMyEnumParam(cbbRooms.Items.Objects[i]);
if aHwnd.MainHwnd > 0 then
begin
ShowMessage(aHwnd.sTitle);
end;
end;
end;
{ Call EnumWindows and fill our array records }
procedure TForm1.FormCreate(Sender: TObject);
var
arInfo: PATMyEnumParam;
begin
iEnumWin:= 0;
EnumWindows(@EnumWindowsProc, LParam(@arInfo));
end;
如果有人能为我指出正确的方向,我将不胜感激。您的代码有很多地方出错。以下是一个非详尽的列表: 您不为阵列分配任何存储。2 将^PATMyEnumParam传递给EnumWindows,然后在回调中将其强制转换为PATMyEnumParam。 您的数组是固定长度的,您不会试图处理对数组的越界访问。 但您最大的问题是,您的代码试图在您能够行走之前运行。它具有完全的复杂性和您需要的所有功能。但是,您还无法成功调用EnumWindows 这里我最大的建议不是细节,而是解决问题的一般性。首先写一段简单的代码。理解它。然后增强它 因此,以下是如何调用EnumerateWindows:
从这里开始,你可以扩展这个概念,因为所有棘手的部分都已经处理好了。特别是指针、强制转换和内存管理。您的代码有很多地方出错。以下是一个非详尽的列表: 您不为阵列分配任何存储。2 将^PATMyEnumParam传递给EnumWindows,然后在回调中将其强制转换为PATMyEnumParam。 您的数组是固定长度的,您不会试图处理对数组的越界访问。 但您最大的问题是,您的代码试图在您能够行走之前运行。它具有完全的复杂性和您需要的所有功能。但是,您还无法成功调用EnumWindows 这里我最大的建议不是细节,而是解决问题的一般性。首先写一段简单的代码。理解它。然后增强它 因此,以下是如何调用EnumerateWindows:
从这里开始,你可以扩展这个概念,因为所有棘手的部分都已经处理好了。特别是指针、投射和内存管理。谢谢,我非常感谢,我知道我想做什么,但正如你所说,指针和内存管理是我的失败之处,我通常会尝试远离这些,并使用Delphi,以便为我处理,作为一名业余程序员,我在处理内存时还有很多需要学习的地方,我以前处理过EnumWindow和EnumChildWindows,没有任何问题,也没有传递参数供其使用,因此不需要真正的内存管理。。再次感谢,我会继续努力,现在看看你是如何使用TList分配记录的,这让它变得更加有趣。TList的最大好处是你不必担心内存分配。谢谢你,我很感激,我知道我想做什么,但正如你所说,指针和内存管理是我的失败之处,我通常会尽量远离这些,使用Delphi的方式让它为我所用,作为一个只有业余爱好者的程序员,我在处理内存时还有很多东西需要学习,我以前处理过EnumWindow和EnumChildWindows,没有任何问题,也没有传递参数让它使用,所以不需要真正的内存管理。。再次感谢,我将继续研究这个问题,现在看看你是如何使用TList分配记录的,这会让它变得更加有趣。TList的最大好处是你不必担心内存分配一个无耻的插件,但是如果你被指针弄丢了,你可能想阅读它。David已经告诉过你你的代码出了什么问题。一个无耻的插件,但是如果你迷失在指针中,你可能想阅读。David已经告诉你你的代码有什么问题了。
program EnumWindowsDemo_17620346;
{$APPTYPE CONSOLE}
uses
System.SysUtils, Winapi.Windows, Generics.Collections;
type
TWindowInfo = record
Handle: HWND;
// expand with more fields in due course
end;
function EnumWindowProc(hwnd: HWND; lParam: LPARAM): BOOL; stdcall;
var
WindowList: TList<TWindowInfo>;
WindowInfo: TWindowInfo;
begin
WindowList := TList<TWindowInfo>(lParam);
WindowInfo.Handle := hwnd;
WindowList.Add(WindowInfo);
Result := True;
end;
procedure Main;
var
WindowList: TList<TWindowInfo>;
WindowInfo: TWindowInfo;
begin
WindowList := TList<TWindowInfo>.Create;
try
EnumWindows(@EnumWindowProc, LPARAM(WindowList));
for WindowInfo in WindowList do
Writeln(WindowInfo.Handle);
finally
WindowList.Free;
end;
end;
begin
Main;
Readln;
end.