【问题标题】:Delphi Pointers, Arrays, HandlesDelphi 指针、数组、句柄
【发布时间】:2013-07-12 17:09:08
【问题描述】:

我无法理解使用自定义记录并制作记录数组然后指向该记录的指针的指针,特别是我想要实现的是使用给定的类名为每个顶级窗口句柄制作一个记录,意思是有超过 1 个,对于每个窗口,我使用 EnumChildWindow 来获取子窗口的句柄。我想记录每个窗口并将其传递给带有标题的组合框,并使记录成为该项目的对象所以我可以稍后通过选择它来访问每个录制的内容。

我的问题是我对指针的处理,在第一次将任何添加到一个数组记录时,我一直被拒绝访问。

在这里休息

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;

如果有人能指出(不是双关语)我正确的方向,我将不胜感激。

【问题讨论】:

标签: delphi pointers enums delphi-xe4 window-handles


【解决方案1】:

您的代码有很多问题。这是一个非详尽的列表:

  1. 您没有为数组分配任何存储空间。2
  2. 您将^PATMyEnumParam 传递给EnumWindows,然后在回调中将其转换为PATMyEnumParam
  3. 您的数组是固定长度的,您不会尝试处理对数组的越界访问。

但你最大的问题是你的代码在你能走路之前就试图运行。它具有完全的复杂性和您需要的所有功能。然而,您还无法成功调用EnumWindows

我在这里最大的建议不是细节,而是解决问题的一般性。从编写一段简单的代码开始。明白它。然后增强它。

因此,在这方面,这里是如何拨打EnumerateWindows

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.

从这里开始你可以扩展这个概念,因为所有棘手的部分都已经处理好了。特别是指针、强制转换和内存管理。

【讨论】:

  • 谢谢,我很感激,我知道我想做什么,但是正如你所说的指针和内存管理是我的失败者,我通常会尽量远离这些,并以这样的方式使用 Delphi它是为我处理的,作为一个只有业余爱好者的程序员,在处理内存时我还有很多东西要学,我之前处理过 EnumWindow 和 EnumChildWindows 没有问题,也没有传递参数供它使用,所以不需要真正的内存管理.. 谢谢再说一次,我会处理这个问题,现在看看你如何使用 TList 分配记录会让它变得更加有趣。
  • TList 的一大好处是你不必担心内存分配问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-06
  • 2011-03-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多