随笔 - 2146  文章 - 19 评论 - 11846 阅读 - 1267万


问题来源: http://www.cnblogs.com/del/archive/2009/10/16/1584488.html#1727205

// EnumWindows 的功能是遍历所有顶层窗口
function EnumWindows(
  lpEnumFunc: TFNWndEnumProc; {回调函数指针}
  lParam: LPARAM              {给回调函数的参数, 它对应回调函数的第二个参数}
): BOOL; stdcall; //成功与否, 其实是返回了回调函数的返回值

// EnumWindows 专用的回调函数的格式:
function EnumWindowsProc(
  hwnd: HWND;        {找到的窗口句柄}
  lParam: LPARAM     {EnumWindows 传给的参数; 因为它是指针, 可传入, 但一般用作传出数据}
): Boolean; stdcall; {函数返回 False 时, 调用它的 EnumWindows 将停止遍历并返回 False}


例一: 获取所有顶层窗口的句柄

//需要个 TListBox 显示数据
function EnumWindowsProc_1(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
begin
  Form1.ListBox1.Items.Add(IntToStr(hwnd));
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_1, 0);
end;


例二: 获取所有顶层窗口的标题(排除无标题窗口)

function EnumWindowsProc_2(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetWindowText(hwnd, buf, SizeOf(buf));
  if buf <> '' then Form1.ListBox1.Items.Add(buf);
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_2, 0);
end;


例三: 查找第一个记事本的句柄

function EnumWindowsProc_3(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  if buf = 'Notepad' then
  begin
    Form1.ListBox1.Items.Add(Format('记事本句柄: %d', [hwnd]));
    Result := False; //如果不需要继续找, 找到第一个就结束
  end
  else
  begin
    Result := True;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  EnumWindows(@EnumWindowsProc_3, 0);
end;


例四: 获取所有顶层窗口的句柄与类名数组:

type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
  TMyStructArray = array of TMyStruct;
  PMyStructArray = ^TMyStructArray;

function EnumWindowsProc_4(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
  p: PMyStructArray;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  p := PMyStructArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].hwnd := hwnd;
  p^[High(p^)].ClassName := buf;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  Arr: TMyStructArray;
begin
  EnumWindows(@EnumWindowsProc_4, Integer(@Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //总数
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一个元素
end;


例五: 重复上一个例子, 如果数组是全局遍历并不靠参数传递, 代码会简单些

type
  TMyStruct = record
    hwnd: HWND;
    ClassName: string;
  end;
var
  Arr: array of TMyStruct;

function EnumWindowsProc_5(hwnd: HWND; lParam: LPARAM): Boolean; stdcall;
var
  buf: array[Byte] of Char;
begin
  GetClassName(hwnd, buf, SizeOf(buf));
  SetLength(Arr, Length(Arr) + 1);
  Arr[High(Arr)].hwnd := hwnd;
  Arr[High(Arr)].ClassName := buf;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(Arr, 0);
  EnumWindows(@EnumWindowsProc_5, Integer(Arr));
  ShowMessage(IntToStr(Length(Arr)));                         //总数
  ShowMessageFmt('%d - %s', [Arr[0].hwnd, Arr[0].ClassName]); //第一个元素
end;


SplendourChiang 的目的是获取进程 ID 和窗口句柄的数组, 按 "例四" 的方法给修改如下:

type
  MyProcessInfo = record
    PID, WinHWND : DWORD;
  end;
  TMyProcessInfoArray = array of MyProcessInfo;
  PMyProcessInfoArray = ^TMyProcessInfoArray;

function MyEnumWindowsProc(Wnd: DWORD; lParam: LPARAM): Bool; stdcall;
var
  PID : DWORD;
  p: PMyProcessInfoArray;
begin
  GetWindowThreadProcessID(Wnd, @PID);
  p := PMyProcessInfoArray(lParam);
  SetLength(p^, Length(p^) + 1);
  p^[High(p^)].PID := PID;
  p^[High(p^)].WinHWND := Wnd;
  Result := True;
end;

procedure TForm1.Button1Click(Sender: TObject);
var
  CC: TMyProcessInfoArray;
begin
  SetLength(CC, 0);
  EnumWindows(@MyEnumWindowsProc, Integer(@CC));
  ShowMessage(IntToStr(Length(CC)));                     //总数
  ShowMessageFmt('%d - %d', [CC[0].PID, CC[0].WinHWND]); //第一个元素
end;

posted on   万一  阅读(14359)  评论(16编辑  收藏  举报
编辑推荐:
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
历史上的今天:
2007-12-18 格式化输出函数(1): Format
2007-12-18 网页压缩、解压
2007-12-18 jQuery 插件
2007-12-18 ini 文件操作记要(2): 使用 TMemIniFile
2007-12-18 Delphi 中的哈希表(2): TStringHash
2007-12-18 Delphi 中的哈希表(1): THashedStringList


点击右上角即可分享
微信分享提示